245 lines
5.8 KiB
C
245 lines
5.8 KiB
C
#include "ast.h"
|
|
|
|
#include <ivy/lang/ast.h>
|
|
#include <ivy/lang/lex.h>
|
|
#include <stdlib.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)
|
|
{
|
|
struct ivy_parser *out = malloc(sizeof *out);
|
|
if (!out) {
|
|
return IVY_ERR_NO_MEMORY;
|
|
}
|
|
|
|
memset(out, 0x0, sizeof *out);
|
|
|
|
push_state(out, IVY_AST_UNIT, struct ivy_ast_unit_node, struct unit_parser_state);
|
|
|
|
*parser = out;
|
|
return IVY_OK;
|
|
}
|
|
|
|
void ivy_parser_destroy(struct ivy_parser *parser)
|
|
{
|
|
free(parser);
|
|
}
|
|
|
|
enum ivy_status ivy_parser_get_status(struct ivy_parser *parser)
|
|
{
|
|
return parser->p_status;
|
|
}
|
|
|
|
static enum ivy_status parse_unit_package(struct ivy_parser *parser, struct ivy_token *tok)
|
|
{
|
|
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)
|
|
{
|
|
}
|
|
|
|
#define ENUM_STR(x) \
|
|
case x: \
|
|
return #x
|
|
|
|
const char *ivy_ast_node_type_to_string(enum ivy_ast_node_type v)
|
|
{
|
|
switch (v) {
|
|
ENUM_STR(IVY_AST_NONE);
|
|
ENUM_STR(IVY_AST_UNIT);
|
|
ENUM_STR(IVY_AST_OP);
|
|
ENUM_STR(IVY_AST_MSG);
|
|
ENUM_STR(IVY_AST_CLASS);
|
|
ENUM_STR(IVY_AST_MSGH);
|
|
ENUM_STR(IVY_AST_PROPERTY);
|
|
ENUM_STR(IVY_AST_LAMBDA);
|
|
ENUM_STR(IVY_AST_UNIT_PACKAGE);
|
|
ENUM_STR(IVY_AST_UNIT_IMPORT);
|
|
ENUM_STR(IVY_AST_INT);
|
|
ENUM_STR(IVY_AST_DOUBLE);
|
|
ENUM_STR(IVY_AST_STRING);
|
|
ENUM_STR(IVY_AST_FSTRING);
|
|
ENUM_STR(IVY_AST_ATOM);
|
|
ENUM_STR(IVY_AST_IDENT);
|
|
ENUM_STR(IVY_AST_FOR_LOOP);
|
|
ENUM_STR(IVY_AST_WHILE_LOOP);
|
|
ENUM_STR(IVY_AST_COND_GROUP);
|
|
ENUM_STR(IVY_AST_COND);
|
|
ENUM_STR(IVY_AST_TUPLE);
|
|
ENUM_STR(IVY_AST_DO);
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
const char *ivy_ast_op_to_string(enum ivy_ast_op v)
|
|
{
|
|
switch (v) {
|
|
ENUM_STR(IVY_OP_NONE);
|
|
ENUM_STR(IVY_OP_ASSIGN);
|
|
ENUM_STR(IVY_OP_ADD);
|
|
ENUM_STR(IVY_OP_SUBTRACT);
|
|
ENUM_STR(IVY_OP_MULTIPLY);
|
|
ENUM_STR(IVY_OP_DIVIDE);
|
|
ENUM_STR(IVY_OP_LESS_THAN);
|
|
ENUM_STR(IVY_OP_GREATER_THAN);
|
|
ENUM_STR(IVY_OP_EQUAL);
|
|
ENUM_STR(IVY_OP_NOT_EQUAL);
|
|
ENUM_STR(IVY_OP_LESS_EQUAL);
|
|
ENUM_STR(IVY_OP_GREATER_EQUAL);
|
|
ENUM_STR(IVY_OP_AND);
|
|
ENUM_STR(IVY_OP_OR);
|
|
ENUM_STR(IVY_OP_IS);
|
|
ENUM_STR(IVY_OP_NOT);
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
const char *ivy_ast_msgh_recipient_type_to_string(enum ivy_ast_msgh_recipient_type v)
|
|
{
|
|
switch (v) {
|
|
ENUM_STR(IVY_AST_MSGH_NONE);
|
|
ENUM_STR(IVY_AST_MSGH_OBJECT);
|
|
ENUM_STR(IVY_AST_MSGH_CLASS);
|
|
default:
|
|
return "";
|
|
}
|
|
}
|