#include "ast.h" #include #include #include #include #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 ""; } }