#include "node.h" #include #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; extern struct ast_node_type block_node_ops; extern struct ast_node_type msg_node_ops; extern struct ast_node_type op_node_ops; extern struct ast_node_type ident_node_ops; extern struct ast_node_type int_node_ops; extern struct ast_node_type double_node_ops; extern struct ast_node_type atom_node_ops; extern struct ast_node_type tuple_node_ops; extern struct ast_node_type string_node_ops; extern struct ast_node_type fstring_node_ops; extern struct ast_node_type cascade_node_ops; extern struct ast_node_type cond_group_node_ops; extern struct ast_node_type cond_node_ops; extern struct ast_node_type match_node_ops; extern struct ast_node_type while_loop_node_ops; extern struct ast_node_type for_loop_node_ops; extern struct ast_node_type return_node_ops; extern struct ast_node_type property_node_ops; extern struct ast_node_type lambda_node_ops; extern struct ast_node_type pkg_node_ops; extern struct ast_node_type pkg_static_node_ops; extern struct ast_node_type pkg_static_item_node_ops; extern struct ast_node_type pkg_dynamic_node_ops; extern struct ast_node_type discard_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, [IVY_AST_BLOCK] = &block_node_ops, [IVY_AST_MSG] = &msg_node_ops, [IVY_AST_OP] = &op_node_ops, [IVY_AST_IDENT] = &ident_node_ops, [IVY_AST_INT] = &int_node_ops, [IVY_AST_DOUBLE] = &double_node_ops, [IVY_AST_ATOM] = &atom_node_ops, [IVY_AST_TUPLE] = &tuple_node_ops, [IVY_AST_STRING] = &string_node_ops, [IVY_AST_FSTRING] = &fstring_node_ops, [IVY_AST_CASCADE] = &cascade_node_ops, [IVY_AST_COND_GROUP] = &cond_group_node_ops, [IVY_AST_COND] = &cond_node_ops, [IVY_AST_MATCH] = &match_node_ops, [IVY_AST_WHILE_LOOP] = &while_loop_node_ops, [IVY_AST_FOR_LOOP] = &for_loop_node_ops, [IVY_AST_RETURN] = &return_node_ops, [IVY_AST_PROPERTY] = &property_node_ops, [IVY_AST_LAMBDA] = &lambda_node_ops, [IVY_AST_PKG] = &pkg_node_ops, [IVY_AST_PKG_STATIC] = &pkg_static_node_ops, [IVY_AST_PKG_ITEM] = &pkg_static_item_node_ops, [IVY_AST_PKG_DYNAMIC] = &pkg_dynamic_node_ops, [IVY_AST_DISCARD] = &discard_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) { const struct ivy_operator *op = NULL; 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_LEFT_BRACKET: case IVY_SYM_LEFT_BRACE: case IVY_SYM_CARET: return TOK_EXPR_BEGIN; case IVY_SYM_COMMA: return TOK_EXPR_ANY; default: op = ivy_operator_get_by_token(tok->t_symbol); return op ? TOK_EXPR_ANY : 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_THROW: return TOK_EXPR_BEGIN; default: op = ivy_operator_get_by_token(tok->t_keyword); return op ? TOK_EXPR_ANY : TOK_EXPR_NONE; return TOK_EXPR_NONE; } default: return TOK_EXPR_NONE; } } token_parse_function get_token_parser( struct ivy_ast_node *context, struct ivy_token *tok) { token_parse_function type_parser = NULL; token_parse_function type_fallback_parser = NULL; token_parse_function token_parser = NULL; token_parse_function expr_begin_parser = NULL; token_parse_function expr_other_parser = NULL; token_parse_function expr_parser = NULL; token_parse_function token_fallback_parser = NULL; const struct ast_node_type *type = get_ast_node_type(context->n_type); if (!type) { return NULL; } token_parser = type->n_token_parsers[__TOK_PARSER_INDEX(tok->t_type)]; token_fallback_parser = type->n_token_parsers[__TOK_PARSER_FALLBACK_INDEX]; token_parse_function better_parser = NULL; switch (tok->t_type) { case IVY_TOK_KEYWORD: type_parser = type->n_keyword_parsers[__KW_PARSER_INDEX(tok->t_keyword)]; if (type->n_keyword_parsers[__KW_PARSER_FALLBACK_INDEX]) { type_fallback_parser = type->n_keyword_parsers[__KW_PARSER_FALLBACK_INDEX]; } break; case IVY_TOK_SYMBOL: type_parser = type->n_symbol_parsers[__SYM_PARSER_INDEX(tok->t_symbol)]; if (type->n_symbol_parsers[__SYM_PARSER_FALLBACK_INDEX]) { type_fallback_parser = type->n_symbol_parsers[__SYM_PARSER_FALLBACK_INDEX]; } break; default: break; } enum token_expr_type expr_type = get_token_expr_type(tok); switch (expr_type) { case TOK_EXPR_BEGIN: expr_begin_parser = type->n_expr_parser.expr_begin; expr_parser = type->n_expr_parser.expr_all; break; case TOK_EXPR_ANY: expr_other_parser = type->n_expr_parser.expr_other; expr_parser = type->n_expr_parser.expr_all; break; default: break; } bool token_has_sub_id = (tok->t_type == IVY_TOK_KEYWORD || tok->t_type == IVY_TOK_SYMBOL); if (type_parser) return type_parser; if (token_parser && !token_has_sub_id) return token_parser; if (expr_begin_parser) return expr_begin_parser; if (expr_other_parser) return expr_other_parser; if (expr_parser) return expr_parser; if (type_fallback_parser) return type_fallback_parser; if (token_parser && token_has_sub_id) return token_parser; if (token_fallback_parser) return token_fallback_parser; return NULL; } struct ivy_ast_node *ast_node_create(enum ivy_ast_node_type type) { const struct ast_node_type *type_info = get_ast_node_type(type); if (!type_info) { return NULL; } struct ivy_ast_node *node = malloc(type_info->n_node_size); if (!node) { return NULL; } memset(node, 0x0, type_info->n_node_size); node->n_type = type; return node; } void ivy_ast_node_to_string(struct ivy_ast_node *node, struct b_string *out) { const struct ast_node_type *type_info = get_ast_node_type(node->n_type); if (!type_info) { return; } if (type_info->n_to_string) { type_info->n_to_string(node, out); } else { b_string_append_cstr( out, ivy_ast_node_type_to_string(node->n_type)); } } 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_SELECTOR); ENUM_STR(IVY_AST_EXPR); ENUM_STR(IVY_AST_LAMBDA); ENUM_STR(IVY_AST_UNIT_PACKAGE); ENUM_STR(IVY_AST_UNIT_IMPORT); ENUM_STR(IVY_AST_DISCARD); 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_CASCADE); ENUM_STR(IVY_AST_COND_GROUP); ENUM_STR(IVY_AST_MATCH); ENUM_STR(IVY_AST_COND); ENUM_STR(IVY_AST_TUPLE); ENUM_STR(IVY_AST_BLOCK); ENUM_STR(IVY_AST_PKG); ENUM_STR(IVY_AST_PKG_STATIC); ENUM_STR(IVY_AST_PKG_ITEM); ENUM_STR(IVY_AST_PKG_DYNAMIC); ENUM_STR(IVY_AST_RETURN); ENUM_STR(IVY_AST_TYPE_COUNT); default: return ""; } }