lang: ast: implement node, parser, and parser state management

This commit is contained in:
2024-11-23 19:28:03 +00:00
parent b630aa009c
commit ed35011931
3 changed files with 153 additions and 4 deletions

View File

@@ -1,9 +1,110 @@
#include "ast.h" #include "ast.h"
#include <ivy/lang/ast.h> #include <ivy/lang/ast.h>
#include <ivy/lang/lex.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define ast_node_create(id, type) _ast_node_create(id, sizeof(type))
#define push_state(parser, node_type_id, node_type_struct, state_struct) _push_state(parser, node_type_id, sizeof(node_type_struct), sizeof(state_struct))
enum pop_state_flags {
ADD_NODE_TO_PARENT = 0x01u,
};
static enum ivy_status unit_add_child(struct ivy_ast_node *parent, struct ivy_ast_node *child)
{
struct ivy_ast_unit_node *unit = (struct ivy_ast_unit_node *)parent;
b_queue_push_back(&unit->n_children, &child->n_entry);
return IVY_OK;
}
typedef enum ivy_status(*node_add_child_function)(struct ivy_ast_node *, struct ivy_ast_node *);
static node_add_child_function node_add_child[] = {
[IVY_AST_UNIT] = unit_add_child,
};
static const size_t nr_node_add_child = sizeof node_add_child / sizeof *node_add_child;
static struct ivy_ast_node *_ast_node_create(enum ivy_ast_node_type type, size_t size)
{
struct ivy_ast_node *node = malloc(size);
if (!node) {
return NULL;
}
memset(node, 0x0, size);
node->n_type = type;
return node;
}
static enum ivy_status ast_node_add_child(struct ivy_ast_node *parent, struct ivy_ast_node *child)
{
if (parent->n_type >= nr_node_add_child) {
return IVY_ERR_NOT_SUPPORTED;
}
node_add_child_function add_child = node_add_child[parent->n_type];
if (!add_child) {
return IVY_ERR_NOT_SUPPORTED;
}
return add_child(parent, child);
}
static struct parser_state *get_state(struct ivy_parser *parser)
{
b_queue_entry *entry = b_queue_last(&parser->p_state);
if (!entry) {
return NULL;
}
struct parser_state *state = b_unbox(struct parser_state, entry, s_entry);
return state;
}
static struct parser_state *_push_state(struct ivy_parser *parser, enum ivy_ast_node_type type, size_t node_size, size_t state_size)
{
struct parser_state *state = malloc(sizeof *state);
if (!state) {
return NULL;
}
memset(state, 0x0, sizeof *state);
b_queue_entry *current_state_entry = b_queue_last(&parser->p_state);
if (current_state_entry) {
struct parser_state *current_state = b_unbox(struct parser_state, current_state_entry, s_entry);
state->s_parent = current_state->s_node;
}
state->s_node = ast_node_create(type, node_size);
b_queue_push_back(&parser->p_state, &state->s_entry);
return state;
}
static void pop_state(struct ivy_parser *parser, enum pop_state_flags flags)
{
if (parser->p_state.q_first == parser->p_state.q_last) {
return;
}
b_queue_entry *entry = b_queue_last(&parser->p_state);
struct parser_state *state = b_unbox(struct parser_state, entry, s_entry);
b_queue_pop_back(&parser->p_state);
if (flags & ADD_NODE_TO_PARENT) {
ast_node_add_child(state->s_parent, state->s_node);
}
free(state);
}
enum ivy_status ivy_parser_create(struct ivy_parser **parser) enum ivy_status ivy_parser_create(struct ivy_parser **parser)
{ {
struct ivy_parser *out = malloc(sizeof *out); struct ivy_parser *out = malloc(sizeof *out);
@@ -13,6 +114,8 @@ enum ivy_status ivy_parser_create(struct ivy_parser **parser)
memset(out, 0x0, sizeof *out); memset(out, 0x0, sizeof *out);
push_state(out, IVY_AST_UNIT, struct ivy_ast_unit_node, struct unit_parser_state);
*parser = out; *parser = out;
return IVY_OK; return IVY_OK;
} }
@@ -27,9 +130,44 @@ enum ivy_status ivy_parser_get_status(struct ivy_parser *parser)
return parser->p_status; return parser->p_status;
} }
struct ivy_ast_node *ivy_parser_read(struct ivy_parser *lex) static enum ivy_status parse_unit_package(struct ivy_parser *parser, struct ivy_token *tok)
{ {
return NULL; return IVY_ERR_NOT_SUPPORTED;
}
static enum ivy_status parse_token_in_unit(struct ivy_parser *parser, struct ivy_token *tok)
{
if (tok->t_type == IVY_TOK_KEYWORD) {
switch (tok->t_keyword) {
case IVY_KW_PACKAGE:
return parse_unit_package(parser, tok);
default:
return IVY_ERR_BAD_SYNTAX;
}
}
}
enum ivy_status ivy_parser_push_token(struct ivy_parser *parser, struct ivy_token *tok)
{
struct parser_state *state = get_state(parser);
if (!state) {
parser->p_status = IVY_ERR_INTERNAL_FAILURE;
return parser->p_status;
}
switch (state->s_node->n_type) {
case IVY_AST_UNIT:
parser->p_status = parse_token_in_unit(parser, tok);
break;
case IVY_AST_UNIT_PACKAGE:
parser->p_status = parse_unit_package(parser, tok);
break;
default:
parser->p_status = IVY_ERR_NOT_SUPPORTED;
break;
}
return parser->p_status;
} }
void ivy_ast_node_destroy(struct ivy_ast_node *node) void ivy_ast_node_destroy(struct ivy_ast_node *node)

View File

@@ -4,9 +4,14 @@
#include <blue/core/queue.h> #include <blue/core/queue.h>
#include <ivy/status.h> #include <ivy/status.h>
struct ivy_parser_state { struct parser_state {
b_queue_entry s_entry; b_queue_entry s_entry;
struct ivy_ast_node *s_parent; struct ivy_ast_node *s_parent;
struct ivy_ast_node *s_node;
};
struct unit_parser_state {
struct parser_state s_base;
}; };
struct ivy_parser { struct ivy_parser {
@@ -16,4 +21,9 @@ struct ivy_parser {
b_queue p_node_queue; b_queue p_node_queue;
}; };
struct ast_node_ops {
enum ivy_status(*n_add_child)(struct ivy_ast_node *, struct ivy_ast_node *);
void(*n_print)(struct ivy_ast_node *);
};
#endif #endif

View File

@@ -65,6 +65,7 @@ struct ivy_ast_node {
struct ivy_ast_unit_node { struct ivy_ast_unit_node {
struct ivy_ast_node n_base; struct ivy_ast_node n_base;
b_queue n_children;
}; };
struct ivy_ast_op_node { struct ivy_ast_op_node {
@@ -229,7 +230,7 @@ IVY_API void ivy_parser_destroy(struct ivy_parser *parser);
IVY_API enum ivy_status ivy_parser_get_status(struct ivy_parser *parser); IVY_API enum ivy_status ivy_parser_get_status(struct ivy_parser *parser);
IVY_API void ivy_parser_push_token(struct ivy_parser *lex, struct ivy_token *tok); IVY_API enum ivy_status ivy_parser_push_token(struct ivy_parser *parser, struct ivy_token *tok);
IVY_API void ivy_ast_node_destroy(struct ivy_ast_node *node); IVY_API void ivy_ast_node_destroy(struct ivy_ast_node *node);