#include "parse.h" #include #include #include #include struct selector_parser_state { struct parser_state s_base; unsigned int s_prev_token; unsigned int s_paren_depth; struct ivy_asm_token *s_prev_label; struct ivy_selector *s_sel; }; static void init_state(struct ivy_asm_parser *ctx, struct parser_state *s) { struct selector_parser_state *state = (struct selector_parser_state *)s; state->s_prev_token = IVY_ASM_SYM_LEFT_PAREN; ivy_selector_create(&state->s_sel); } static enum ivy_status parse_ident( struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) { struct selector_parser_state *state = (struct selector_parser_state *)asm_parser_get_state(ctx); if (state->s_prev_token == IVY_ASM_TOK_LABEL && state->s_prev_label) { ivy_selector_add_arg( state->s_sel, state->s_prev_label->t_str, tok->t_str); ivy_asm_token_destroy(tok); ivy_asm_token_destroy(state->s_prev_label); state->s_prev_label = tok; state->s_prev_token = IVY_ASM_TOK_LABEL; return IVY_OK; } if (state->s_prev_token != IVY_ASM_SYM_LEFT_PAREN && state->s_prev_token != IVY_ASM_SYM_HYPHEN && state->s_prev_token != IVY_ASM_SYM_PLUS) { return IVY_ERR_BAD_SYNTAX; } ivy_selector_set_name(state->s_sel, tok->t_str); ivy_asm_token_destroy(tok); state->s_prev_token = IVY_ASM_TOK_IDENT; return IVY_OK; } static enum ivy_status parse_label( struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) { struct selector_parser_state *state = (struct selector_parser_state *)asm_parser_get_state(ctx); if (state->s_prev_token != IVY_ASM_SYM_LEFT_PAREN && state->s_prev_token != IVY_ASM_TOK_LABEL && state->s_prev_token != IVY_ASM_SYM_HYPHEN && state->s_prev_token != IVY_ASM_SYM_PLUS) { return IVY_ERR_BAD_SYNTAX; } if (state->s_prev_label) { ivy_selector_add_arg(state->s_sel, state->s_prev_label->t_str, NULL); ivy_asm_token_destroy(state->s_prev_label); state->s_prev_label = NULL; } state->s_prev_label = tok; state->s_prev_token = IVY_ASM_TOK_LABEL; return IVY_OK; } static enum ivy_status parse_hyphen( struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) { struct selector_parser_state *state = (struct selector_parser_state *)asm_parser_get_state(ctx); if (state->s_prev_token != IVY_ASM_SYM_LEFT_PAREN) { return IVY_ERR_BAD_SYNTAX; } ivy_selector_set_recipient(state->s_sel, IVY_SEL_OBJECT); state->s_prev_token = IVY_ASM_SYM_HYPHEN; return IVY_OK; } static enum ivy_status parse_plus( struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) { struct selector_parser_state *state = (struct selector_parser_state *)asm_parser_get_state(ctx); if (state->s_prev_token != IVY_ASM_SYM_LEFT_PAREN) { return IVY_ERR_BAD_SYNTAX; } ivy_selector_set_recipient(state->s_sel, IVY_SEL_CLASS); state->s_prev_token = IVY_ASM_SYM_PLUS; return IVY_OK; } static enum ivy_status parse_left_paren( struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) { struct selector_parser_state *state = (struct selector_parser_state *)asm_parser_get_state(ctx); if (state->s_prev_token != IVY_ASM_TOK_IDENT) { return IVY_ERR_BAD_SYNTAX; } if (state->s_paren_depth > 0) { return IVY_ERR_BAD_SYNTAX; } state->s_paren_depth++; state->s_prev_token = IVY_ASM_SYM_LEFT_PAREN; return IVY_OK; } static enum ivy_status parse_right_paren( struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) { struct selector_parser_state *state = (struct selector_parser_state *)asm_parser_get_state(ctx); if (state->s_prev_token != IVY_ASM_TOK_IDENT && state->s_prev_token != IVY_ASM_TOK_LABEL && state->s_prev_token != IVY_ASM_SYM_RIGHT_PAREN) { return IVY_ERR_BAD_SYNTAX; } if (state->s_prev_label) { ivy_selector_add_arg(state->s_sel, state->s_prev_label->t_str, NULL); ivy_asm_token_destroy(state->s_prev_label); state->s_prev_label = NULL; } if (state->s_paren_depth > 0) { state->s_paren_depth--; return IVY_OK; } asm_parser_pop_state(ctx, state->s_sel); return IVY_OK; } struct parser_state_type selector_parser_state_type = { .n_init_state = init_state, .n_state_size = sizeof(struct selector_parser_state), .n_token_parsers = { TOK_PARSER(IDENT, parse_ident), TOK_PARSER(LABEL, parse_label), }, .n_symbol_parsers = { SYM_PARSER(HYPHEN, parse_hyphen), SYM_PARSER(PLUS, parse_plus), SYM_PARSER(LEFT_PAREN, parse_left_paren), SYM_PARSER(RIGHT_PAREN, parse_right_paren), }, };