summaryrefslogtreecommitdiff
path: root/parser.c
diff options
context:
space:
mode:
authorCarson Fleming <cflems@cflems.net>2026-07-18 22:34:54 -0700
committerCarson Fleming <cflems@cflems.net>2026-07-18 22:46:47 -0700
commitfeb1cac139ca5aa2ba76ac6a0a318bced03d8638 (patch)
treee107f774e08daed3dedd5d39345d2b725b2d171d /parser.c
parent385419f95c6b9c35a7c2a6168f82f7aa4a44e22b (diff)
downloadccc-feb1cac139ca5aa2ba76ac6a0a318bced03d8638.tar.gz
loop support
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c59
1 files changed, 58 insertions, 1 deletions
diff --git a/parser.c b/parser.c
index 4779e73..b094780 100644
--- a/parser.c
+++ b/parser.c
@@ -128,7 +128,7 @@ static void parse_expr_assign(struct expr_node* p_node) {
.type = LVAL_VAR_REF,
.inner.var_ref = p_node->inner.var_ref,
};
- return;
+ break;
default:
PARSER_PANIC("expression is not assignable");
}
@@ -346,6 +346,55 @@ static void parse_if(struct if_node* p_node) {
scope_pop(&scope);
}
+static void parse_while(struct loop_node* p_node) {
+ expect_kw("while");
+
+ scope_push(&scope);
+ p_node->scope = scope;
+
+ expect(TK_LPAREN);
+ p_node->cond = protected_alloc(sizeof(struct expr_node));
+ parse_expr(p_node->cond);
+ expect(TK_RPAREN);
+
+ p_node->body = protected_alloc(sizeof(struct stmt_node));
+ parse_stmt(p_node->body);
+
+ scope_pop(&scope);
+}
+
+static void parse_for(struct loop_node* p_node) {
+ expect_kw("for");
+
+ scope_push(&scope);
+ p_node->scope = scope;
+
+ expect(TK_LPAREN);
+ peek_or_panic();
+ if (tok.type != TK_SEMI) {
+ p_node->init = protected_alloc(sizeof(struct expr_node));
+ parse_expr(p_node->init);
+ }
+ expect(TK_SEMI);
+ peek_or_panic();
+ if (tok.type != TK_SEMI) {
+ p_node->cond = protected_alloc(sizeof(struct expr_node));
+ parse_expr(p_node->cond);
+ }
+ expect(TK_SEMI);
+ peek_or_panic();
+ if (tok.type != TK_RPAREN) {
+ p_node->incr = protected_alloc(sizeof(struct expr_node));
+ parse_expr(p_node->incr);
+ }
+ expect(TK_RPAREN);
+
+ p_node->body = protected_alloc(sizeof(struct stmt_node));
+ parse_stmt(p_node->body);
+
+ scope_pop(&scope);
+}
+
static void parse_stmt_assign(struct stmt_node* p_node) {
peek_or_panic();
if (tok.type != TK_ASSIGN) return;
@@ -385,6 +434,14 @@ static void parse_stmt(struct stmt_node* p_node) {
p_node->type = STMT_IF;
parse_if(&p_node->inner.if_);
return;
+ } else if (strcmp(tok.data.ident, "while") == 0) {
+ p_node->type = STMT_LOOP;
+ parse_while(&p_node->inner.loop);
+ return;
+ } else if (strcmp(tok.data.ident, "for") == 0) {
+ p_node->type = STMT_LOOP;
+ parse_for(&p_node->inner.loop);
+ return;
} else if (strcmp(tok.data.ident, "return") == 0) {
p_node->type = STMT_RETURN;
parse_return(&p_node->inner.return_);