#include "ctx.h" #include "expr/expr.h" #include "iterate.h" #include "ivy/status.h" #include "node.h" #include #include #include struct tuple_parser_state { struct parser_state s_base; struct ivy_ast_node *s_prev_node; unsigned int s_prev; b_queue s_items; }; static void finalise_tuple(struct tuple_parser_state *state) { struct ivy_ast_tuple_node *tuple = (struct ivy_ast_tuple_node *)state->s_base.s_node; tuple->n_members = state->s_items; state->s_items = B_QUEUE_INIT; } struct token_parse_result parse_comma(struct ivy_parser *ctx, struct ivy_token *tok) { struct tuple_parser_state *state = parser_get_state(ctx, struct tuple_parser_state); if (state->s_prev != IVY_SYM_LEFT_PAREN && state->s_prev != IVY_SYM_COMMA) { /* token not expected at this time. */ return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); } if (!state->s_prev_node) { /* empty tuple member */ return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); } b_queue_push_back(&state->s_items, &state->s_prev_node->n_entry); state->s_prev_node = NULL; state->s_prev = IVY_SYM_COMMA; struct expr_parser_state *expr = (struct expr_parser_state *)parser_push_state(ctx, IVY_AST_EXPR, 0); expr_add_terminator(expr, IVY_SYM_COMMA); expr_add_terminator(expr, IVY_SYM_RIGHT_PAREN); expr->s_subexpr_depth = 1; return PARSE_RESULT(IVY_OK, 0); } struct token_parse_result parse_right_paren(struct ivy_parser *ctx, struct ivy_token *tok) { struct tuple_parser_state *state = parser_get_state(ctx, struct tuple_parser_state); if (state->s_prev != IVY_SYM_COMMA) { /* token not expected at this time. */ return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); } if (!state->s_prev_node) { /* empty tuple member */ return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); } b_queue_push_back(&state->s_items, &state->s_prev_node->n_entry); state->s_prev_node = NULL; state->s_prev = IVY_SYM_RIGHT_PAREN; finalise_tuple(state); parser_pop_state(ctx, STATE_ADD_NODE_TO_PARENT); return PARSE_RESULT(IVY_OK, 0); } static enum ivy_status add_child( struct parser_state *parent, struct ivy_ast_node *child) { struct tuple_parser_state *state = (struct tuple_parser_state *)parent; if (state->s_prev_node) { return IVY_ERR_BAD_SYNTAX; } state->s_prev_node = child; return IVY_OK; } static void init_state(struct ivy_parser *ctx, struct parser_state *sp, uintptr_t arg) { struct tuple_parser_state *state = (struct tuple_parser_state *)sp; state->s_prev = IVY_SYM_LEFT_PAREN; if (arg) { /* arg is the first node in the tuple */ struct ivy_ast_node *item = (struct ivy_ast_node *)arg; b_queue_push_back(&state->s_items, &item->n_entry); state->s_prev = IVY_SYM_COMMA; } struct expr_parser_state *expr = (struct expr_parser_state *)parser_push_state(ctx, IVY_AST_EXPR, 0); expr_add_terminator(expr, IVY_SYM_COMMA); expr_add_terminator(expr, IVY_SYM_RIGHT_PAREN); expr->s_subexpr_depth = 1; } static void collect_children( struct ivy_ast_node *node, struct ivy_ast_node_iterator *iterator) { struct ivy_ast_tuple_node *tuple = (struct ivy_ast_tuple_node *)node; b_queue_iterator it = {0}; b_queue_foreach (&it, &tuple->n_members) { struct ivy_ast_node *item = b_unbox(struct ivy_ast_node, it.entry, n_entry); ast_node_iterator_enqueue_node(iterator, node, item); } } struct ast_node_type tuple_node_ops = { .n_add_child = add_child, .n_init_state = init_state, .n_collect_children = collect_children, .n_state_size = sizeof(struct tuple_parser_state), .n_node_size = sizeof(struct ivy_ast_tuple_node), .n_symbol_parsers = { SYM_PARSER(COMMA, parse_comma), SYM_PARSER(RIGHT_PAREN, parse_right_paren), }, };