summaryrefslogtreecommitdiff
path: root/parser.c
diff options
context:
space:
mode:
authorCarson Fleming <cflems@cflems.net>2026-07-17 03:20:34 -0700
committerCarson Fleming <cflems@cflems.net>2026-07-17 03:20:34 -0700
commit155d1971b7cd56d3206808c36c6b40357bc31cbb (patch)
treeb06b4c59d7eaa8084985b82e73b975d194eb8929 /parser.c
parent99af8891f6672493939bf3b43084082884e28d04 (diff)
downloadccc-155d1971b7cd56d3206808c36c6b40357bc31cbb.tar.gz
almost fibonacci but it needs the type checker
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c45
1 files changed, 33 insertions, 12 deletions
diff --git a/parser.c b/parser.c
index e078ae9..9a3e7f3 100644
--- a/parser.c
+++ b/parser.c
@@ -30,10 +30,9 @@ static void* protected_alloc(size_t sz) {
static void unexpected_token(enum token_type expected) {
/* TODO: print what token was expected */
- PARSER_PANIC("unexpected token");
+ PARSER_PANIC("unexpected token; expected %d", expected);
}
-/* TODO: reorganize the lexer to make peek cheaper */
static void peek_or_panic() {
if (!lexer_peek(&tok))
PARSER_PANIC("unexpected EOF");
@@ -311,6 +310,25 @@ static void parse_group(struct group_node* p_node) {
expect(TK_RCURLY);
}
+static void parse_if(struct if_node* p_node) {
+ expect_kw("if");
+
+ expect(TK_LPAREN);
+ p_node->cond = protected_alloc(sizeof(struct expr_node));
+ parse_expr(p_node->cond);
+ expect(TK_RPAREN);
+
+ p_node->true_branch = protected_alloc(sizeof(struct stmt_node));
+ parse_stmt(p_node->true_branch);
+
+ peek_or_panic();
+ if (tok.type != TK_IDENT || strcmp(tok.data.ident, "else") != 0) return;
+ expect_kw("else");
+
+ p_node->false_branch = protected_alloc(sizeof(struct stmt_node));
+ parse_stmt(p_node->false_branch);
+}
+
static void parse_stmt_assign(struct stmt_node* p_node) {
peek_or_panic();
if (tok.type != TK_ASSIGN) return;
@@ -346,7 +364,11 @@ static void parse_stmt(struct stmt_node* p_node) {
parse_group(&p_node->inner.group);
return;
case TK_IDENT:
- if (strcmp(tok.data.ident, "return") == 0) {
+ if (strcmp(tok.data.ident, "if") == 0) {
+ p_node->type = STMT_IF;
+ parse_if(&p_node->inner.if_);
+ return;
+ } else if (strcmp(tok.data.ident, "return") == 0) {
p_node->type = STMT_RETURN;
parse_return(&p_node->inner.return_);
break;
@@ -383,6 +405,14 @@ static void parse_fn_decl(struct fn_decl_node* p_node) {
expect(TK_IDENT);
p_node->name = tok.data.ident;
+ scope_define_var(scope, (struct var_def) {
+ .name = p_node->name,
+ .loc = {
+ .type = STO_FN,
+ .decl = p_node,
+ },
+ });
+
expect(TK_LPAREN);
scope_push(&scope);
@@ -393,15 +423,6 @@ static void parse_fn_decl(struct fn_decl_node* p_node) {
expect(TK_RPAREN);
- /* defining here makes recursion possible */
- scope_define_var(scope, (struct var_def) {
- .name = p_node->name,
- .loc = {
- .type = STO_FN,
- .decl = p_node,
- },
- });
-
parse_group(&p_node->body);
scope_pop(&scope);