#include "node.h" #include #include #include #include extern struct ast_node_type unit_node_ops; extern struct ast_node_type unit_package_node_ops; extern struct ast_node_type unit_import_node_ops; extern struct ast_node_type class_node_ops; extern struct ast_node_type msgh_node_ops; extern struct ast_node_type selector_node_ops; extern struct ast_node_type expr_node_ops; static const struct ast_node_type *node_ops[] = { [IVY_AST_UNIT] = &unit_node_ops, [IVY_AST_UNIT_PACKAGE] = &unit_package_node_ops, [IVY_AST_UNIT_IMPORT] = &unit_import_node_ops, [IVY_AST_CLASS] = &class_node_ops, [IVY_AST_MSGH] = &msgh_node_ops, [IVY_AST_SELECTOR] = &selector_node_ops, [IVY_AST_EXPR] = &expr_node_ops, }; static const size_t nr_node_ops = sizeof node_ops / sizeof node_ops[0]; const struct ast_node_type *get_ast_node_type(enum ivy_ast_node_type type) { if (type >= nr_node_ops) { return NULL; } return node_ops[type]; } enum token_expr_type get_token_expr_type(struct ivy_token *tok) { switch (tok->t_type) { case IVY_TOK_IDENT: case IVY_TOK_INT: case IVY_TOK_DOUBLE: case IVY_TOK_STRING: case IVY_TOK_STR_START: case IVY_TOK_ATOM: return TOK_EXPR_BEGIN; case IVY_TOK_SYMBOL: switch (tok->t_symbol) { case IVY_SYM_LEFT_PAREN: case IVY_SYM_CARET: return TOK_EXPR_BEGIN; case IVY_SYM_PLUS: case IVY_SYM_HYPHEN: case IVY_SYM_FORWARD_SLASH: case IVY_SYM_ASTERISK: case IVY_SYM_PIPE: case IVY_SYM_COMMA: case IVY_SYM_SEMICOLON: case IVY_SYM_EQUAL: case IVY_SYM_PLUS_EQUAL: case IVY_SYM_HYPHEN_EQUAL: case IVY_SYM_FORWARD_SLASH_EQUAL: case IVY_SYM_ASTERISK_EQUAL: case IVY_SYM_AMPERSAND_EQUAL: case IVY_SYM_PIPE_EQUAL: case IVY_SYM_PERCENT_EQUAL: case IVY_SYM_CARET_EQUAL: case IVY_SYM_PERCENT: case IVY_SYM_AMPERSAND: case IVY_SYM_DOUBLE_EQUAL: case IVY_SYM_DOUBLE_LEFT_ANGLE: case IVY_SYM_DOUBLE_RIGHT_ANGLE: case IVY_SYM_DOUBLE_LEFT_ANGLE_EQUAL: case IVY_SYM_DOUBLE_RIGHT_ANGLE_EQUAL: case IVY_SYM_HYPHEN_RIGHT_ANGLE: return TOK_EXPR_ANY; default: return TOK_EXPR_NONE; } case IVY_TOK_KEYWORD: switch (tok->t_keyword) { case IVY_KW_IF: case IVY_KW_ELSE: case IVY_KW_MATCH: case IVY_KW_FOR: case IVY_KW_WHILE: case IVY_KW_TRY: case IVY_KW_CATCH: case IVY_KW_NOT: case IVY_KW_THROW: return TOK_EXPR_BEGIN; case IVY_KW_IS: case IVY_KW_AND: case IVY_KW_OR: return TOK_EXPR_ANY; default: return TOK_EXPR_NONE; } default: return TOK_EXPR_NONE; } } token_parse_function get_token_parser( struct ivy_ast_node *context, struct ivy_token *tok) { const struct ast_node_type *type = get_ast_node_type(context->n_type); if (!type) { return NULL; } token_parse_function generic_parser = type->n_token_parsers[tok->t_type]; if (!generic_parser) { generic_parser = type->n_token_parsers[IVY_TOK_NONE]; } token_parse_function better_parser = NULL; switch (tok->t_type) { case IVY_TOK_KEYWORD: better_parser = type->n_keyword_parsers[tok->t_keyword]; if (type->n_keyword_parsers[IVY_KW_NONE]) { generic_parser = type->n_keyword_parsers[IVY_KW_NONE]; } break; case IVY_TOK_SYMBOL: better_parser = type->n_symbol_parsers[tok->t_symbol]; if (type->n_symbol_parsers[IVY_SYM_NONE]) { generic_parser = type->n_symbol_parsers[IVY_SYM_NONE]; } break; default: break; } if (better_parser) { return better_parser; } enum token_expr_type expr_type = get_token_expr_type(tok); switch (expr_type) { case TOK_EXPR_BEGIN: better_parser = type->n_expr_parser.expr_begin ? type->n_expr_parser.expr_begin : type->n_expr_parser.expr_all; break; case TOK_EXPR_ANY: better_parser = type->n_expr_parser.expr_other ? type->n_expr_parser.expr_other : type->n_expr_parser.expr_all; break; default: break; } return better_parser ? better_parser : generic_parser; } struct ivy_ast_node *ast_node_create_with_size( 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; } enum ivy_status ast_node_add_child( struct ivy_ast_node *parent, struct ivy_ast_node *child) { const struct ast_node_type *ops = get_ast_node_type(parent->n_type); if (!ops) { return IVY_ERR_NOT_SUPPORTED; } enum ivy_status (*add_child)(struct ivy_ast_node *, struct ivy_ast_node *) = ops->n_add_child; if (!add_child) { return IVY_ERR_NOT_SUPPORTED; } return add_child(parent, child); } static enum ivy_status node_print( struct ivy_ast_node *node, struct ivy_ast_node_iterator *it) { for (unsigned int i = 0; i < node->n_it.it_depth; i++) { fputs(" ", stdout); } const struct ast_node_type *type = get_ast_node_type(node->n_type); if (type && type->n_print) { type->n_print(node); } else { printf("%s\n", ivy_ast_node_type_to_string(node->n_type)); } return IVY_OK; } void ivy_ast_node_print(struct ivy_ast_node *node) { struct ivy_ast_node_iterator it = {0}; ivy_ast_node_iterate(node, &it, node_print); } 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); ENUM_STR(IVY_AST_TYPE_COUNT); 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 ""; } }