diff --git a/lang/ast/expr/arith.c b/lang/ast/expr/arith.c index fe49816..8511de8 100644 --- a/lang/ast/expr/arith.c +++ b/lang/ast/expr/arith.c @@ -110,6 +110,23 @@ enum ivy_status arith_push_operand( b_queue_push_back(&state->s_output_queue, &v->n_entry); break; } + case IVY_TOK_KEYWORD: { + struct ivy_ast_node *v = NULL; + switch (tok->t_keyword) { + case IVY_KW_BREAK: + v = ast_node_create(IVY_AST_LOOP_BREAK); + break; + case IVY_KW_CONTINUE: + v = ast_node_create(IVY_AST_LOOP_REPEAT); + break; + default: + return IVY_ERR_BAD_SYNTAX; + } + + ivy_ast_node_set_bounds_from_token((struct ivy_ast_node *)v, tok); + b_queue_push_back(&state->s_output_queue, &v->n_entry); + break; + } default: return IVY_ERR_BAD_SYNTAX; } diff --git a/lang/ast/expr/expr.c b/lang/ast/expr/expr.c index 5ff28e2..7730258 100644 --- a/lang/ast/expr/expr.c +++ b/lang/ast/expr/expr.c @@ -78,8 +78,10 @@ struct ast_node_type expr_node_ops = { .n_keyword_parsers = { /* statement keywords */ KW_PARSER(FOR, stmt_parse_for), - KW_PARSER(TRY, stmt_parse_try), KW_PARSER(WHILE, stmt_parse_while), + KW_PARSER(BREAK, stmt_parse_break), + KW_PARSER(CONTINUE, stmt_parse_continue), + KW_PARSER(TRY, stmt_parse_try), KW_PARSER(MATCH, stmt_parse_match), KW_PARSER(IF, stmt_parse_if), KW_PARSER(THEN, stmt_parse_end), diff --git a/lang/ast/expr/expr.h b/lang/ast/expr/expr.h index b71861a..d62162c 100644 --- a/lang/ast/expr/expr.h +++ b/lang/ast/expr/expr.h @@ -174,5 +174,9 @@ struct token_parse_result stmt_parse_else( struct ivy_parser *ctx, struct ivy_token *tok); struct token_parse_result stmt_parse_end( struct ivy_parser *ctx, struct ivy_token *tok); +extern struct token_parse_result stmt_parse_break( + struct ivy_parser *ctx, struct ivy_token *tok); +extern struct token_parse_result stmt_parse_continue( + struct ivy_parser *ctx, struct ivy_token *tok); #endif diff --git a/lang/ast/expr/stmt.c b/lang/ast/expr/stmt.c index b0068c6..c352341 100644 --- a/lang/ast/expr/stmt.c +++ b/lang/ast/expr/stmt.c @@ -232,3 +232,35 @@ struct token_parse_result stmt_parse_end( result.r_flags |= PARSE_REPEAT_TOKEN; return result; } + +struct token_parse_result stmt_parse_break( + struct ivy_parser *ctx, struct ivy_token *tok) +{ + struct expr_parser_state *state + = parser_get_state(ctx, struct expr_parser_state); + + if (state->s_prev_component != EXPR_CMP_NONE) { + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); + } + + arith_push_operand(state, tok); + state->s_prev_component = EXPR_CMP_KEYWORD; + + return PARSE_RESULT(IVY_OK, 0); +} + +struct token_parse_result stmt_parse_continue( + struct ivy_parser *ctx, struct ivy_token *tok) +{ + struct expr_parser_state *state + = parser_get_state(ctx, struct expr_parser_state); + + if (state->s_prev_component != EXPR_CMP_NONE) { + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); + } + + arith_push_operand(state, tok); + state->s_prev_component = EXPR_CMP_KEYWORD; + + return PARSE_RESULT(IVY_OK, 0); +} diff --git a/lang/ast/loop-control.c b/lang/ast/loop-control.c new file mode 100644 index 0000000..59e16e1 --- /dev/null +++ b/lang/ast/loop-control.c @@ -0,0 +1,21 @@ +#include "ctx.h" +#include "node.h" + +#include + +static void to_string(struct ivy_ast_node *node, b_string *str) +{ + b_string_append_cstrf(str, "%s", ivy_ast_node_type_to_string(node->n_type)); +} + +struct ast_node_type loop_break_node_ops = { + .n_to_string = to_string, + .n_state_size = sizeof(struct parser_state), + .n_node_size = sizeof(struct ivy_ast_loop_break_node), +}; + +struct ast_node_type loop_repeat_node_ops = { + .n_to_string = to_string, + .n_state_size = sizeof(struct parser_state), + .n_node_size = sizeof(struct ivy_ast_loop_repeat_node), +}; diff --git a/lang/ast/node.c b/lang/ast/node.c index b276265..b07aedb 100644 --- a/lang/ast/node.c +++ b/lang/ast/node.c @@ -30,6 +30,8 @@ extern struct ast_node_type cond_node_ops; extern struct ast_node_type match_node_ops; extern struct ast_node_type while_loop_node_ops; extern struct ast_node_type for_loop_node_ops; +extern struct ast_node_type loop_break_node_ops; +extern struct ast_node_type loop_repeat_node_ops; extern struct ast_node_type return_node_ops; extern struct ast_node_type property_node_ops; extern struct ast_node_type lambda_node_ops; @@ -66,6 +68,8 @@ static const struct ast_node_type *node_ops[] = { [IVY_AST_MATCH] = &match_node_ops, [IVY_AST_WHILE_LOOP] = &while_loop_node_ops, [IVY_AST_FOR_LOOP] = &for_loop_node_ops, + [IVY_AST_LOOP_BREAK] = &loop_break_node_ops, + [IVY_AST_LOOP_REPEAT] = &loop_repeat_node_ops, [IVY_AST_RETURN] = &return_node_ops, [IVY_AST_PROPERTY] = &property_node_ops, [IVY_AST_LAMBDA] = &lambda_node_ops, @@ -121,6 +125,8 @@ enum token_expr_type get_token_expr_type(struct ivy_token *tok) case IVY_KW_MATCH: case IVY_KW_FOR: case IVY_KW_WHILE: + case IVY_KW_BREAK: + case IVY_KW_CONTINUE: case IVY_KW_TRY: case IVY_KW_THROW: return TOK_EXPR_BEGIN; @@ -357,6 +363,8 @@ const char *ivy_ast_node_type_to_string(enum ivy_ast_node_type v) ENUM_STR(IVY_AST_IDENT); ENUM_STR(IVY_AST_FOR_LOOP); ENUM_STR(IVY_AST_WHILE_LOOP); + ENUM_STR(IVY_AST_LOOP_BREAK); + ENUM_STR(IVY_AST_LOOP_REPEAT); ENUM_STR(IVY_AST_CASCADE); ENUM_STR(IVY_AST_COND_GROUP); ENUM_STR(IVY_AST_MATCH);