From 94c10dfbb2c9b39bf175e022b494d8d0e8b676cc Mon Sep 17 00:00:00 2001 From: Max Wash Date: Fri, 6 Dec 2024 13:46:58 +0000 Subject: [PATCH] lang: ast: implement parsing of f-strings --- lang/ast/expr/arith.c | 82 +++++++++++++++++++++++++++++++++---------- lang/ast/expr/expr.c | 3 ++ lang/ast/expr/expr.h | 6 ++++ lang/ast/node.c | 2 ++ lang/ast/string.c | 76 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 151 insertions(+), 18 deletions(-) diff --git a/lang/ast/expr/arith.c b/lang/ast/expr/arith.c index ecc0c28..cac9ac9 100644 --- a/lang/ast/expr/arith.c +++ b/lang/ast/expr/arith.c @@ -416,6 +416,29 @@ enum ivy_status expr_finalise_arith( return IVY_OK; } +struct token_parse_result arith_parse_fstring( + struct ivy_parser *ctx, struct ivy_token *tok) +{ + struct expr_parser_state *state + = parser_get_state(ctx, struct expr_parser_state); + + if (state->s_type == EXPR_TYPE_STMT) { + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); + } + + if (state->s_prev_component == EXPR_CMP_OPERAND) { + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); + } + + state->s_type = EXPR_TYPE_ARITH; + state->s_prev_component = EXPR_CMP_OPERAND; + state->s_prev_token = tok->t_type; + + parser_push_state(ctx, IVY_AST_FSTRING, 0); + + return PARSE_RESULT(IVY_OK, 0); +} + struct token_parse_result arith_parse_operand( struct ivy_parser *ctx, struct ivy_token *tok) { @@ -601,6 +624,47 @@ struct token_parse_result arith_parse_left_paren( return PARSE_RESULT(IVY_OK, 0); } +struct token_parse_result arith_parse_right_paren( + struct ivy_parser *ctx, struct ivy_token *tok) +{ + struct expr_parser_state *state + = parser_get_state(ctx, struct expr_parser_state); + + if (state->s_type != EXPR_TYPE_ARITH) { + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); + } + + if (state->s_paren_depth == 0 && state->s_sub_type == EXPR_SUBTYPE_NONE) { + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); + } + + state->s_prev_token = IVY_SYM_RIGHT_PAREN; + return expr_finalise_and_return(ctx, state); +} + +struct token_parse_result arith_parse_left_brace( + struct ivy_parser *ctx, struct ivy_token *tok) +{ + return PARSE_RESULT(IVY_ERR_NOT_SUPPORTED, 0); + +} + +struct token_parse_result arith_parse_right_brace( + struct ivy_parser *ctx, struct ivy_token *tok) +{ + struct expr_parser_state *state + = parser_get_state(ctx, struct expr_parser_state); + + if (state->s_terminator == IVY_SYM_RIGHT_BRACE) { + state->s_prev_token = IVY_SYM_RIGHT_BRACE; + struct token_parse_result result = expr_finalise_and_return(ctx, state); + result.r_flags = PARSE_REPEAT_TOKEN; + return result; + } + + return PARSE_RESULT(IVY_ERR_NOT_SUPPORTED, 0); +} + static struct ivy_ast_selector_node *keyword_selector_from_label_list(b_queue *labels) { struct ivy_ast_selector_node *sel @@ -693,24 +757,6 @@ static struct ivy_ast_msg_node *expr_finalise_complex_msg( return msg; } -struct token_parse_result arith_parse_right_paren( - struct ivy_parser *ctx, struct ivy_token *tok) -{ - struct expr_parser_state *state - = parser_get_state(ctx, struct expr_parser_state); - - if (state->s_type != EXPR_TYPE_ARITH) { - return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); - } - - if (state->s_paren_depth == 0 && state->s_sub_type == EXPR_SUBTYPE_NONE) { - return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); - } - - state->s_prev_token = IVY_SYM_RIGHT_PAREN; - return expr_finalise_and_return(ctx, state); -} - static enum ivy_status begin_cascade_operation(struct ivy_parser *ctx) { struct expr_parser_state *state diff --git a/lang/ast/expr/expr.c b/lang/ast/expr/expr.c index 78a7698..8e1cfe0 100644 --- a/lang/ast/expr/expr.c +++ b/lang/ast/expr/expr.c @@ -26,12 +26,15 @@ struct ast_node_type expr_node_ops = { TOK_PARSER(DOUBLE, arith_parse_operand), TOK_PARSER(ATOM, arith_parse_operand), TOK_PARSER(STRING, arith_parse_operand), + TOK_PARSER(STR_START, arith_parse_fstring), TOK_PARSER(SYMBOL, arith_parse_operator), TOK_PARSER(LABEL, arith_parse_label), }, .n_symbol_parsers = { SYM_PARSER(LEFT_PAREN, arith_parse_left_paren), SYM_PARSER(RIGHT_PAREN, arith_parse_right_paren), + SYM_PARSER(LEFT_BRACE, arith_parse_left_brace), + SYM_PARSER(RIGHT_BRACE, arith_parse_right_brace), SYM_PARSER(SEMICOLON, arith_parse_semicolon), SYM_PARSER(UNDERSCORE, arith_parse_operand), SYM_PARSER(CARET, arith_parse_caret), diff --git a/lang/ast/expr/expr.h b/lang/ast/expr/expr.h index 6359ba7..4f8e264 100644 --- a/lang/ast/expr/expr.h +++ b/lang/ast/expr/expr.h @@ -106,6 +106,8 @@ extern enum ivy_status arith_add_child( extern struct token_parse_result arith_parse_ident( struct ivy_parser *ctx, struct ivy_token *tok); +extern struct token_parse_result arith_parse_fstring( + struct ivy_parser *ctx, struct ivy_token *tok); extern struct token_parse_result arith_parse_operand( struct ivy_parser *ctx, struct ivy_token *tok); extern struct token_parse_result arith_parse_operator( @@ -116,6 +118,10 @@ extern struct token_parse_result arith_parse_left_paren( struct ivy_parser *ctx, struct ivy_token *tok); extern struct token_parse_result arith_parse_right_paren( struct ivy_parser *ctx, struct ivy_token *tok); +extern struct token_parse_result arith_parse_left_brace( + struct ivy_parser *ctx, struct ivy_token *tok); +extern struct token_parse_result arith_parse_right_brace( + struct ivy_parser *ctx, struct ivy_token *tok); extern struct token_parse_result arith_parse_semicolon( struct ivy_parser *ctx, struct ivy_token *tok); extern struct token_parse_result arith_parse_dot( diff --git a/lang/ast/node.c b/lang/ast/node.c index 483539a..b266e8d 100644 --- a/lang/ast/node.c +++ b/lang/ast/node.c @@ -20,6 +20,7 @@ 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 string_node_ops; +extern struct ast_node_type fstring_node_ops; extern struct ast_node_type cascade_node_ops; extern struct ast_node_type cond_group_node_ops; extern struct ast_node_type cond_node_ops; @@ -45,6 +46,7 @@ static const struct ast_node_type *node_ops[] = { [IVY_AST_DOUBLE] = &double_node_ops, [IVY_AST_ATOM] = &atom_node_ops, [IVY_AST_STRING] = &string_node_ops, + [IVY_AST_FSTRING] = &fstring_node_ops, [IVY_AST_CASCADE] = &cascade_node_ops, [IVY_AST_COND_GROUP] = &cond_group_node_ops, [IVY_AST_COND] = &cond_node_ops, diff --git a/lang/ast/string.c b/lang/ast/string.c index 78584ed..0151465 100644 --- a/lang/ast/string.c +++ b/lang/ast/string.c @@ -1,7 +1,83 @@ #include "ctx.h" +#include "expr/expr.h" #include "node.h" +struct token_parse_result parse_string( + struct ivy_parser *ctx, struct ivy_token *tok) +{ + struct parser_state *state = parser_get_state_generic(ctx); + struct ivy_ast_fstring_node *parent = (struct ivy_ast_fstring_node *)state->s_node; + struct ivy_ast_string_node *child = (struct ivy_ast_string_node *)ast_node_create(IVY_AST_STRING); + + if (!child) { + return PARSE_RESULT(IVY_ERR_NO_MEMORY, 0); + } + + child->n_value = tok; + b_queue_push_back(&parent->n_value, &child->n_base.n_entry); + return PARSE_RESULT(IVY_OK, 0); +} + +struct token_parse_result parse_left_brace( + struct ivy_parser *ctx, struct ivy_token *tok) +{ + struct expr_parser_state *expr = (struct expr_parser_state *)parser_push_state(ctx, IVY_AST_EXPR, 0); + expr->s_terminator = IVY_SYM_RIGHT_BRACE; + return PARSE_RESULT(IVY_OK, 0); +} + +struct token_parse_result parse_right_brace( + struct ivy_parser *ctx, struct ivy_token *tok) +{ + return PARSE_RESULT(IVY_OK, 0); +} + +struct token_parse_result parse_str_end( + struct ivy_parser *ctx, struct ivy_token *tok) +{ + 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 ivy_ast_fstring_node *str + = (struct ivy_ast_fstring_node *)parent->s_node; + + b_queue_push_back(&str->n_value, &child->n_entry); + + return IVY_OK; +} + +static void collect_children( + struct ivy_ast_node *node, struct ivy_ast_node_iterator *iterator) +{ + struct ivy_ast_fstring_node *str = (struct ivy_ast_fstring_node *)node; + b_queue_iterator it = {0}; + b_queue_foreach (&it, &str->n_value) { + struct ivy_ast_node *child + = b_unbox(struct ivy_ast_node, it.entry, n_entry); + ast_node_iterator_enqueue_node(iterator, node, child); + } +} + struct ast_node_type string_node_ops = { .n_state_size = sizeof(struct parser_state), .n_node_size = sizeof(struct ivy_ast_string_node), }; + +struct ast_node_type fstring_node_ops = { + .n_add_child = add_child, + .n_collect_children = collect_children, + .n_state_size = sizeof(struct parser_state), + .n_node_size = sizeof(struct ivy_ast_fstring_node), + .n_token_parsers = { + TOK_PARSER(STRING, parse_string), + TOK_PARSER(STR_END, parse_str_end), + }, + .n_symbol_parsers = { + SYM_PARSER(LEFT_BRACE, parse_left_brace), + SYM_PARSER(RIGHT_BRACE, parse_right_brace), + }, +};