From 753afd7d8773f0fcbe7cc386b5f6e71504fe8b0f Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 8 Dec 2024 12:28:47 +0000 Subject: [PATCH] lang: ast: implement parsing of tuples --- lang/ast/expr/arith.c | 37 ++++++++++-- lang/ast/expr/stmt.c | 2 +- lang/ast/node.c | 2 + lang/ast/tuple.c | 130 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 166 insertions(+), 5 deletions(-) diff --git a/lang/ast/expr/arith.c b/lang/ast/expr/arith.c index 082feb1..6fb3802 100644 --- a/lang/ast/expr/arith.c +++ b/lang/ast/expr/arith.c @@ -619,8 +619,10 @@ struct token_parse_result arith_parse_left_paren( struct expr_parser_state *sub_expr = (struct expr_parser_state *)parser_push_state( ctx, IVY_AST_EXPR, 0); + expr_copy_terminators(state, sub_expr); sub_expr->s_paren_depth = state->s_paren_depth + 1; sub_expr->s_subexpr_depth = state->s_subexpr_depth + 1; + sub_expr->s_sub_type = EXPR_SUBTYPE_PAREN; return PARSE_RESULT(IVY_OK, 0); } @@ -631,6 +633,13 @@ struct token_parse_result arith_parse_right_paren( struct expr_parser_state *state = parser_get_state(ctx, struct expr_parser_state); + if (expr_terminates_at_token(state, IVY_SYM_RIGHT_PAREN)) { + struct token_parse_result result + = expr_finalise_and_return(ctx, state); + result.r_flags = PARSE_REPEAT_TOKEN; + return result; + } + if (state->s_type != EXPR_TYPE_ARITH) { return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); } @@ -1146,11 +1155,31 @@ struct token_parse_result arith_parse_comma( if (state->s_paren_depth > 0 && (state->s_prev_component == EXPR_CMP_OPERAND || state->s_prev_component == EXPR_CMP_MSG)) { - /* tuple. */ - return PARSE_RESULT(IVY_ERR_NOT_SUPPORTED, 0); + struct ivy_ast_node *item = NULL; + struct token_parse_result result + = expr_finalise(ctx, state, IVY_PRECEDENCE_ASSIGN, &item); + + if (result.r_status != IVY_OK) { + return result; + } + + if (!item) { + /* empty tuple member expression. */ + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); + } + + if (state->s_sub_type == EXPR_SUBTYPE_PAREN && b_queue_empty(&state->s_output_queue) && b_queue_empty(&state->s_operator_stack)) { + parser_pop_state(ctx, 0); + } else { + /* the tuple parser will handle the parentheses for us. */ + state->s_paren_depth--; + } + + parser_push_state(ctx, IVY_AST_TUPLE, (uintptr_t)item); + return PARSE_RESULT(IVY_OK, 0); } - state->s_prev_token = IVY_SYM_DOT; + state->s_prev_token = IVY_SYM_COMMA; return expr_finalise_and_return(ctx, state); } @@ -1289,4 +1318,4 @@ enum ivy_status arith_add_child( } return IVY_OK; -} +} \ No newline at end of file diff --git a/lang/ast/expr/stmt.c b/lang/ast/expr/stmt.c index 5a00649..952a2e1 100644 --- a/lang/ast/expr/stmt.c +++ b/lang/ast/expr/stmt.c @@ -196,4 +196,4 @@ struct token_parse_result stmt_parse_end( struct token_parse_result result = expr_finalise_and_return(ctx, state); result.r_flags |= PARSE_REPEAT_TOKEN; return result; -} +} \ No newline at end of file diff --git a/lang/ast/node.c b/lang/ast/node.c index 6da4391..ac271c5 100644 --- a/lang/ast/node.c +++ b/lang/ast/node.c @@ -20,6 +20,7 @@ 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; @@ -52,6 +53,7 @@ static const struct ast_node_type *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, diff --git a/lang/ast/tuple.c b/lang/ast/tuple.c index e69de29..47dc422 100644 --- a/lang/ast/tuple.c +++ b/lang/ast/tuple.c @@ -0,0 +1,130 @@ +#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), + }, +};