2024-11-24 11:10:42 +00:00
|
|
|
#include "ctx.h"
|
|
|
|
|
|
2024-12-06 09:53:09 +00:00
|
|
|
#include "../debug.h"
|
2024-11-24 11:10:42 +00:00
|
|
|
#include "node.h"
|
|
|
|
|
|
|
|
|
|
#include <blue/core/queue.h>
|
|
|
|
|
#include <ivy/lang/ast.h>
|
|
|
|
|
#include <stddef.h>
|
2024-12-02 07:56:27 +00:00
|
|
|
#include <stdio.h>
|
2024-11-24 11:10:42 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
2024-12-05 19:37:58 +00:00
|
|
|
#ifdef IVY_LANG_DEBUG
|
2024-12-02 07:56:27 +00:00
|
|
|
static void print_state_stack(struct ivy_parser *parser)
|
|
|
|
|
{
|
|
|
|
|
b_queue_iterator it = {0};
|
|
|
|
|
b_queue_foreach (&it, &parser->p_state) {
|
|
|
|
|
struct parser_state *state
|
|
|
|
|
= b_unbox(struct parser_state, it.entry, s_entry);
|
2024-12-06 09:53:09 +00:00
|
|
|
debug_printf(
|
|
|
|
|
" %s\n",
|
|
|
|
|
ivy_ast_node_type_to_string(state->s_node->n_type));
|
2024-12-02 07:56:27 +00:00
|
|
|
}
|
|
|
|
|
}
|
2024-12-05 19:37:58 +00:00
|
|
|
#endif
|
2024-12-02 07:56:27 +00:00
|
|
|
|
2024-11-24 11:10:42 +00:00
|
|
|
enum ivy_status ivy_parser_create(struct ivy_parser **parser)
|
|
|
|
|
{
|
|
|
|
|
struct ivy_parser *out = malloc(sizeof *out);
|
|
|
|
|
if (!out) {
|
|
|
|
|
return IVY_ERR_NO_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(out, 0x0, sizeof *out);
|
|
|
|
|
|
2024-12-04 16:35:19 +00:00
|
|
|
parser_push_state(out, IVY_AST_UNIT, 0);
|
2024-11-24 11:10:42 +00:00
|
|
|
|
|
|
|
|
*parser = out;
|
|
|
|
|
return IVY_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-17 23:15:48 +01:00
|
|
|
void ivy_parser_destroy(struct ivy_parser *parser, struct ivy_ast_node **result)
|
2024-11-24 11:10:42 +00:00
|
|
|
{
|
2025-04-17 23:15:48 +01:00
|
|
|
struct ivy_ast_node *root = NULL;
|
|
|
|
|
|
|
|
|
|
b_queue_iterator it;
|
|
|
|
|
b_queue_iterator_begin(&parser->p_state, &it);
|
|
|
|
|
while (b_queue_iterator_is_valid(&it)) {
|
|
|
|
|
struct parser_state *state
|
|
|
|
|
= b_unbox(struct parser_state, it.entry, s_entry);
|
|
|
|
|
b_queue_iterator_erase(&it);
|
|
|
|
|
|
|
|
|
|
if (root) {
|
|
|
|
|
ivy_ast_node_destroy(root);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
root = state->s_node;
|
|
|
|
|
free(state);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result) {
|
|
|
|
|
*result = root;
|
|
|
|
|
} else if (root) {
|
|
|
|
|
ivy_ast_node_destroy(root);
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-24 11:10:42 +00:00
|
|
|
free(parser);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum ivy_status ivy_parser_get_status(struct ivy_parser *parser)
|
|
|
|
|
{
|
|
|
|
|
return parser->p_status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum ivy_status ivy_parser_push_token(
|
|
|
|
|
struct ivy_parser *parser, struct ivy_token *tok)
|
|
|
|
|
{
|
2024-11-26 21:30:40 +00:00
|
|
|
while (true) {
|
|
|
|
|
struct parser_state *state = parser_get_state_generic(parser);
|
|
|
|
|
if (!state) {
|
|
|
|
|
parser->p_status = IVY_ERR_INTERNAL_FAILURE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
token_parse_function func = get_token_parser(state->s_node, tok);
|
|
|
|
|
if (func) {
|
|
|
|
|
struct token_parse_result result = func(parser, tok);
|
|
|
|
|
parser->p_status = result.r_status;
|
|
|
|
|
|
2024-12-05 19:37:58 +00:00
|
|
|
#ifdef IVY_LANG_DEBUG
|
|
|
|
|
debug_printf("states (after token)\n");
|
2024-12-02 07:56:27 +00:00
|
|
|
print_state_stack(parser);
|
2024-12-05 19:37:58 +00:00
|
|
|
#endif
|
2024-11-26 21:30:40 +00:00
|
|
|
if (result.r_flags & PARSE_REPEAT_TOKEN) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tok->t_type == IVY_TOK_LINEFEED) {
|
|
|
|
|
ivy_token_destroy(tok);
|
|
|
|
|
parser->p_status = IVY_OK;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parser->p_status = IVY_ERR_BAD_SYNTAX;
|
|
|
|
|
break;
|
2024-11-25 16:49:43 +00:00
|
|
|
}
|
|
|
|
|
|
2024-11-26 21:30:40 +00:00
|
|
|
return parser->p_status;
|
2024-11-24 11:10:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct parser_state *parser_get_state_generic(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;
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-06 09:53:09 +00:00
|
|
|
struct parser_state *parser_get_parent_state_generic(
|
|
|
|
|
struct ivy_parser *parser, enum ivy_ast_node_type type)
|
2024-12-03 21:57:44 +00:00
|
|
|
{
|
|
|
|
|
b_queue_entry *entry = b_queue_last(&parser->p_state);
|
|
|
|
|
if (!entry) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
entry = b_queue_prev(entry);
|
|
|
|
|
if (!entry) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct parser_state *state = b_unbox(struct parser_state, entry, s_entry);
|
|
|
|
|
|
|
|
|
|
if (state->s_node->n_type != type) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return state;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-24 11:46:42 +00:00
|
|
|
struct parser_state *parser_push_state(
|
2024-12-04 16:35:19 +00:00
|
|
|
struct ivy_parser *parser, enum ivy_ast_node_type type, uintptr_t arg)
|
2024-11-24 11:10:42 +00:00
|
|
|
{
|
2024-11-24 11:42:43 +00:00
|
|
|
const struct ast_node_type *node_type = get_ast_node_type(type);
|
|
|
|
|
if (!node_type) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct parser_state *state = malloc(node_type->n_state_size);
|
2024-11-24 11:10:42 +00:00
|
|
|
if (!state) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-24 11:42:43 +00:00
|
|
|
memset(state, 0x0, node_type->n_state_size);
|
2024-11-24 11:10:42 +00:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-28 22:06:25 +00:00
|
|
|
state->s_node = ast_node_create(type);
|
2024-11-26 21:30:40 +00:00
|
|
|
b_queue_push_back(&parser->p_state, &state->s_entry);
|
2024-11-24 11:10:42 +00:00
|
|
|
|
2024-11-24 11:42:43 +00:00
|
|
|
if (node_type->n_init_state) {
|
2024-12-04 16:35:19 +00:00
|
|
|
node_type->n_init_state(parser, state, arg);
|
2024-11-24 11:10:42 +00:00
|
|
|
}
|
|
|
|
|
|
2024-12-05 19:37:58 +00:00
|
|
|
#ifdef IVY_LANG_DEBUG
|
|
|
|
|
debug_printf("states (after push)\n");
|
2024-12-02 07:56:27 +00:00
|
|
|
print_state_stack(parser);
|
2024-12-05 19:37:58 +00:00
|
|
|
#endif
|
2024-11-24 11:10:42 +00:00
|
|
|
return state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void parser_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);
|
|
|
|
|
|
2024-12-04 16:35:19 +00:00
|
|
|
if (state && state->s_node && (flags & STATE_ADD_NODE_TO_PARENT)) {
|
2024-12-02 07:56:27 +00:00
|
|
|
parser_add_child(parser, state->s_node);
|
2024-11-24 11:10:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(state);
|
2024-12-02 07:56:27 +00:00
|
|
|
|
2024-12-05 19:37:58 +00:00
|
|
|
#ifdef IVY_LANG_DEBUG
|
|
|
|
|
debug_printf("states (after pop)\n");
|
2024-12-02 07:56:27 +00:00
|
|
|
print_state_stack(parser);
|
2024-12-05 19:37:58 +00:00
|
|
|
#endif
|
2024-11-24 11:10:42 +00:00
|
|
|
}
|
2024-11-24 16:12:31 +00:00
|
|
|
|
2024-12-02 07:56:27 +00:00
|
|
|
void parser_replace_current_node(
|
|
|
|
|
struct ivy_parser *parser, struct ivy_ast_node *new_node)
|
2024-11-28 22:06:25 +00:00
|
|
|
{
|
|
|
|
|
struct parser_state *state = parser_get_state_generic(parser);
|
|
|
|
|
if (!state) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ivy_ast_node_destroy(state->s_node);
|
|
|
|
|
state->s_node = new_node;
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-02 07:56:27 +00:00
|
|
|
enum ivy_status parser_add_child(
|
|
|
|
|
struct ivy_parser *parser, struct ivy_ast_node *new_node)
|
|
|
|
|
{
|
|
|
|
|
struct parser_state *state = parser_get_state_generic(parser);
|
|
|
|
|
if (!state) {
|
|
|
|
|
return IVY_ERR_NOT_SUPPORTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const struct ast_node_type *node_type
|
|
|
|
|
= get_ast_node_type(state->s_node->n_type);
|
|
|
|
|
if (!node_type || !node_type->n_add_child) {
|
|
|
|
|
return IVY_ERR_NOT_SUPPORTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return node_type->n_add_child(state, new_node);
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-24 16:12:31 +00:00
|
|
|
bool ivy_parser_is_node_complete(struct ivy_parser *parser)
|
|
|
|
|
{
|
|
|
|
|
return (parser->p_state.q_first == parser->p_state.q_last);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ivy_ast_node *ivy_parser_root_node(struct ivy_parser *parser)
|
|
|
|
|
{
|
|
|
|
|
b_queue_entry *entry = b_queue_first(&parser->p_state);
|
|
|
|
|
struct parser_state *state = b_unbox(struct parser_state, entry, s_entry);
|
2024-11-25 16:49:43 +00:00
|
|
|
return state ? state->s_node : NULL;
|
2024-11-24 16:12:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ivy_ast_node *ivy_parser_dequeue_node(struct ivy_parser *parser)
|
|
|
|
|
{
|
|
|
|
|
b_queue_entry *entry = b_queue_first(&parser->p_state);
|
|
|
|
|
struct parser_state *state = b_unbox(struct parser_state, entry, s_entry);
|
2024-11-26 13:08:39 +00:00
|
|
|
|
2024-11-25 16:49:43 +00:00
|
|
|
if (!state) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-24 16:12:31 +00:00
|
|
|
if (state->s_node->n_type != IVY_AST_UNIT) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ivy_ast_unit_node *unit = (struct ivy_ast_unit_node *)state->s_node;
|
|
|
|
|
|
|
|
|
|
entry = b_queue_pop_front(&unit->n_children);
|
2024-11-26 13:08:39 +00:00
|
|
|
|
2024-11-24 16:12:31 +00:00
|
|
|
if (!entry) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return b_unbox(struct ivy_ast_node, entry, n_entry);
|
2024-11-26 13:08:39 +00:00
|
|
|
}
|