#include "ctx.h" #include "ivy/status.h" #include "node.h" #include #include struct selector_parser_state { struct parser_state s_base; unsigned int s_prev; }; static enum ivy_status parse_ident(struct ivy_parser *ctx, struct ivy_token *tok) { struct selector_parser_state *state = parser_get_state(ctx, struct selector_parser_state); struct ivy_ast_selector_node *sel = (struct ivy_ast_selector_node *)state->s_base.s_node; if (state->s_prev == 0) { /* message name */ sel->n_msg_name = tok; state->s_prev = IVY_TOK_IDENT; return IVY_OK; } if (state->s_prev == IVY_TOK_LABEL) { /* internal parameter name */ b_queue_push_back(&sel->n_arg_names, &tok->t_entry); state->s_prev = IVY_TOK_IDENT; return IVY_OK; } return IVY_ERR_BAD_SYNTAX; } static enum ivy_status parse_label(struct ivy_parser *ctx, struct ivy_token *tok) { struct selector_parser_state *state = parser_get_state(ctx, struct selector_parser_state); struct ivy_ast_selector_node *sel = (struct ivy_ast_selector_node *)state->s_base.s_node; if (state->s_prev != IVY_TOK_IDENT && state->s_prev != IVY_SYM_LEFT_PAREN) { return IVY_ERR_BAD_SYNTAX; } b_queue_push_back(&sel->n_arg_labels, &tok->t_entry); return IVY_OK; } static enum ivy_status parse_linefeed(struct ivy_parser *ctx, struct ivy_token *tok) { struct selector_parser_state *state = parser_get_state(ctx, struct selector_parser_state); struct ivy_ast_selector_node *sel = (struct ivy_ast_selector_node *)state->s_base.s_node; if (!b_queue_empty(&sel->n_arg_labels) && state->s_prev != IVY_SYM_RIGHT_PAREN) { return IVY_ERR_BAD_SYNTAX; } if (state->s_prev != IVY_TOK_IDENT) { return IVY_ERR_BAD_SYNTAX; } parser_pop_state(ctx, STATE_ADD_NODE_TO_PARENT); return IVY_OK; } static enum ivy_status parse_left_paren( struct ivy_parser *ctx, struct ivy_token *tok) { struct selector_parser_state *state = parser_get_state(ctx, struct selector_parser_state); struct ivy_ast_selector_node *sel = (struct ivy_ast_selector_node *)state->s_base.s_node; if (state->s_prev != IVY_TOK_IDENT || !b_queue_empty(&sel->n_arg_labels)) { return IVY_ERR_BAD_SYNTAX; } return IVY_OK; } static enum ivy_status parse_right_paren( struct ivy_parser *ctx, struct ivy_token *tok) { struct selector_parser_state *state = parser_get_state(ctx, struct selector_parser_state); struct ivy_ast_selector_node *sel = (struct ivy_ast_selector_node *)state->s_base.s_node; if (state->s_prev != IVY_TOK_IDENT || !b_queue_empty(&sel->n_arg_labels)) { return IVY_ERR_BAD_SYNTAX; } return IVY_OK; } static enum ivy_status parse_pipe(struct ivy_parser *ctx, struct ivy_token *tok) { struct selector_parser_state *state = parser_get_state(ctx, struct selector_parser_state); struct ivy_ast_selector_node *sel = (struct ivy_ast_selector_node *)state->s_base.s_node; if (!b_queue_empty(&sel->n_arg_labels) && state->s_prev != IVY_SYM_RIGHT_PAREN) { return IVY_ERR_BAD_SYNTAX; } if (state->s_prev != IVY_TOK_IDENT) { return IVY_ERR_BAD_SYNTAX; } parser_pop_state(ctx, STATE_ADD_NODE_TO_PARENT); return IVY_OK; } static void init_state(struct ivy_parser *ctx, struct parser_state *sp) { struct selector_parser_state *state = (struct selector_parser_state *)sp; state->s_prev = 0; } struct ast_node_type msgh_node_ops = { .n_init_state = init_state, .n_state_size = sizeof(struct selector_parser_state), .n_node_size = sizeof(struct ivy_ast_selector_node), .n_token_parsers = { [IVY_TOK_IDENT] = parse_ident, [IVY_TOK_LABEL] = parse_label, }, .n_symbol_parsers = { [IVY_SYM_LEFT_PAREN] = parse_left_paren, [IVY_SYM_RIGHT_PAREN] = parse_right_paren, [IVY_SYM_PIPE] = parse_pipe, }, };