#include #include #include #include #include "parse.h" extern struct parser_state_type unit_parser_state_type; extern struct parser_state_type constpool_parser_state_type; extern struct parser_state_type ident_parser_state_type; extern struct parser_state_type selector_parser_state_type; extern struct parser_state_type atom_parser_state_type; static const struct parser_state_type *parser_state_types[] = { [ASM_PARSER_UNIT] = &unit_parser_state_type, [ASM_PARSER_CONSTPOOL] = &constpool_parser_state_type, [ASM_PARSER_IDENT] = &ident_parser_state_type, [ASM_PARSER_SELECTOR] = &selector_parser_state_type, [ASM_PARSER_ATOM] = &atom_parser_state_type, }; static const size_t nr_parser_state_types = sizeof parser_state_types / sizeof parser_state_types[0]; enum ivy_status ivy_asm_parser_create(struct ivy_asm_parser **out) { struct ivy_asm_parser *parser = malloc(sizeof *parser); if (!parser) { return IVY_ERR_NO_MEMORY; } memset(parser, 0x0, sizeof *parser); asm_parser_push_state(parser, ASM_PARSER_UNIT); *out = parser; return IVY_OK; } void ivy_asm_parser_destroy(struct ivy_asm_parser *p) { free(p); } void ivy_asm_parser_set_assembler( struct ivy_asm_parser *p, struct ivy_assembler *as) { p->p_assembler = as; } static token_parse_function get_token_parser(struct parser_state *state, struct ivy_asm_token *tok) { const struct parser_state_type *type = state->s_type; if (!type) { return NULL; } token_parse_function specific_parser = NULL; token_parse_function specific_fallback_parser = NULL; token_parse_function token_parser = type->n_token_parsers[__TOK_PARSER_INDEX(tok->t_type)]; token_parse_function token_fallback_parser = type->n_token_parsers[__TOK_PARSER_FALLBACK_INDEX]; switch (tok->t_type) { case IVY_ASM_TOK_SYMBOL: specific_parser = type->n_symbol_parsers[__SYM_PARSER_INDEX(tok->t_symbol)]; specific_fallback_parser = type->n_symbol_parsers[__SYM_PARSER_FALLBACK_INDEX]; break; case IVY_ASM_TOK_KEYWORD: specific_parser = type->n_keyword_parsers[__KW_PARSER_INDEX(tok->t_keyword)]; specific_fallback_parser = type->n_keyword_parsers[__KW_PARSER_FALLBACK_INDEX]; break; default: break; } if (specific_parser) return specific_parser; if (specific_fallback_parser) return specific_fallback_parser; if (token_parser) return token_parser; if (token_fallback_parser) return token_fallback_parser; return NULL; } enum ivy_status ivy_asm_parser_push_token( struct ivy_asm_parser *p, struct ivy_asm_token *tok) { struct parser_state *state = asm_parser_get_state(p); if (!state) { return IVY_ERR_NOT_SUPPORTED; } token_parse_function f = get_token_parser(state, tok); if (!f) { if (tok->t_type == IVY_ASM_TOK_LINEFEED) { ivy_asm_token_destroy(tok); return IVY_OK; } return IVY_ERR_BAD_SYNTAX; } return f(p, tok); } static const struct parser_state_type *get_parser_state_type(enum parser_state_type_id type) { if (type < 0 || type >= nr_parser_state_types) { return NULL; } return parser_state_types[type]; } struct parser_state *asm_parser_push_state(struct ivy_asm_parser *parser, enum parser_state_type_id type) { const struct parser_state_type *type_info = get_parser_state_type(type); if (!type_info) { return NULL; } struct parser_state *state = malloc(type_info->n_state_size); if (!state) { return NULL; } memset(state, 0x0, type_info->n_state_size); state->s_type = type_info; if (type_info->n_init_state) { type_info->n_init_state(parser, state); } b_queue_push_back(&parser->p_state, &state->s_entry); return state; } void asm_parser_pop_state(struct ivy_asm_parser *parser, void *ret) { b_queue_entry *last = b_queue_pop_back(&parser->p_state); if (!last) { return; } struct parser_state *state = b_unbox(struct parser_state, last, s_entry); if (state->s_type->n_finish_state) { state->s_type->n_finish_state(parser, state); } free(state); state = asm_parser_get_state(parser); if (state) { state->s_previous_value = ret; } } struct parser_state *asm_parser_get_state(struct ivy_asm_parser *parser) { b_queue_entry *last = b_queue_last(&parser->p_state); if (!last) { return NULL; } return b_unbox(struct parser_state, last, s_entry); }