aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-10-02 15:47:53 +0200
committerHimbeer <himbeer@disroot.org>2024-10-02 15:50:02 +0200
commit5ba544c4e016de3d61a296ceeaf7c4a143f3c118 (patch)
tree2d3e948856a315fa9a9fca8da16d7c6d48c511ed
parent6dcaccdab64366d086898dc289fda9d80b98e636 (diff)
Implement optional break expressions
-rw-r--r--include/parse.h7
-rw-r--r--src/parse.c23
2 files changed, 21 insertions, 9 deletions
diff --git a/include/parse.h b/include/parse.h
index b3e8eee..0889f91 100644
--- a/include/parse.h
+++ b/include/parse.h
@@ -28,6 +28,11 @@ struct ast_return {
struct ast_expr *value;
};
+struct ast_break {
+ const char *label;
+ struct ast_expr *value;
+};
+
struct ast_declaration {
bool mut;
const char *name;
@@ -72,7 +77,7 @@ struct ast_statement {
enum statement action;
union {
struct ast_return ret;
- const char *brklabel;
+ struct ast_break brk;
struct ast_declaration decl;
struct ast_assign assign;
struct call_e call;
diff --git a/src/parse.c b/src/parse.c
index 3fa1498..ee115d8 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -1107,14 +1107,14 @@ parse_return(struct lexer *lexer, struct ast_return *out)
}
static bool
-parse_break(struct lexer *lexer, const char **out)
+parse_break(struct lexer *lexer, struct ast_break *out)
{
if (!match(lexer, T_BREAK)) {
return false;
}
if (!match(lexer, T_COLON)) {
- *out = NULL;
+ out->label = NULL;
return true;
}
@@ -1122,20 +1122,26 @@ parse_break(struct lexer *lexer, const char **out)
if (lex(lexer, &label) != T_NAME) {
error(lex_loc(lexer), "syntax error: expected name");
}
- *out = label.info.str;
+ out->label = label.info.str;
+
+ out->value = must_malloc(sizeof(struct ast_expr));
+ if (!parse_expr(lexer, out->value)) {
+ free(out->value);
+ out->value = NULL;
+ }
return true;
}
static bool
-parse_continue(struct lexer *lexer, const char **out)
+parse_continue(struct lexer *lexer, struct ast_break *out)
{
if (!match(lexer, T_CONTINUE)) {
return false;
}
if (!match(lexer, T_COLON)) {
- *out = NULL;
+ out->label = NULL;
return true;
}
@@ -1143,8 +1149,9 @@ parse_continue(struct lexer *lexer, const char **out)
if (lex(lexer, &label) != T_NAME) {
error(lex_loc(lexer), "syntax error: expected name");
}
- *out = label.info.str;
+ out->label = label.info.str;
+ out->value = NULL;
return true;
}
@@ -1307,14 +1314,14 @@ parse_statement(struct lexer *lexer, struct ast_statement *out)
}
return true;
}
- if (parse_break(lexer, &out->stmt.brklabel)) {
+ if (parse_break(lexer, &out->stmt.brk)) {
out->action = STM_BREAK;
if (!match(lexer, T_SEMICOLON)) {
error(lex_loc(lexer), "syntax error: expected semicolon");
}
return true;
}
- if (parse_continue(lexer, &out->stmt.brklabel)) {
+ if (parse_continue(lexer, &out->stmt.brk)) {
out->action = STM_CONTINUE;
if (!match(lexer, T_SEMICOLON)) {
error(lex_loc(lexer), "syntax error: expected semicolon");