summaryrefslogtreecommitdiff
path: root/parser.c
diff options
context:
space:
mode:
authorCarson Fleming <cflems@cflems.net>2026-07-21 14:36:02 -0700
committerCarson Fleming <cflems@cflems.net>2026-07-21 14:36:02 -0700
commit0cabbd2a0853c332c82af621b8716643741d758a (patch)
tree4d1772e07ff1b81e00b563f877c6f1ead3305a8d /parser.c
parentf87e953223b7d498fc5401247952c08ab1e08f93 (diff)
downloadccc-0cabbd2a0853c332c82af621b8716643741d758a.tar.gz
more faithful grammar
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c110
1 files changed, 57 insertions, 53 deletions
diff --git a/parser.c b/parser.c
index 28e36e3..7bad30f 100644
--- a/parser.c
+++ b/parser.c
@@ -124,34 +124,29 @@ static void parse_var_ref(struct var_ref_node* p_node) {
}
static void parse_expr_assign(struct expr_node* p_node) {
- switch (p_node->type) {
- case EXPR_VAR_REF:
- p_node->inner.assign.lval = (struct lval_node) {
- .type = LVAL_VAR_REF,
- .inner.var_ref = p_node->inner.var_ref,
- };
- break;
- default:
- PARSER_PANIC("expression is not assignable");
- }
+ struct expr_node* lval = protected_alloc(sizeof(struct expr_node));
+ *lval = *p_node;
p_node->type = EXPR_ASSIGN;
- p_node->inner.assign.rval = protected_alloc(sizeof(struct expr_node));
+ struct assign_node* a_node = &p_node->inner.assign;
+ a_node->lval = lval;
expect(TK_ASSIGN);
- parse_expr(p_node->inner.assign.rval);
+ a_node->rval = protected_alloc(sizeof(struct expr_node));
+ parse_expr(a_node->rval);
}
-static void parse_args_eval(struct args_eval_node** pp_arg) {
+static void parse_expr_list(struct expr_list_node* p_node) {
for (;;) {
- *pp_arg = protected_alloc(sizeof(struct args_eval_node));
- (*pp_arg)->expr = protected_alloc(sizeof(struct expr_node));
- parse_expr((*pp_arg)->expr);
- pp_arg = &((*pp_arg)->next);
+ p_node->expr = protected_alloc(sizeof(struct expr_node));
+ parse_expr(p_node->expr);
peek_or_panic();
- if (tok.type == TK_RPAREN) break;
+ if (tok.type != TK_COMMA) break;
expect(TK_COMMA);
+
+ p_node->next = protected_alloc(sizeof(struct expr_list_node));
+ p_node = p_node->next;
}
}
@@ -174,7 +169,11 @@ static void parse_expr_call(struct expr_node* p_node) {
expect(TK_LPAREN);
peek_or_panic();
- if (tok.type != TK_RPAREN) parse_args_eval(&p_node->inner.call.args);
+ if (tok.type != TK_RPAREN) {
+ p_node->inner.call.args =
+ protected_alloc(sizeof(struct expr_list_node));
+ parse_expr_list(p_node->inner.call.args);
+ }
expect(TK_RPAREN);
}
@@ -286,6 +285,13 @@ static void parse_var_decl(struct var_decl_node* p_node) {
});
if (p_node->def_ref == NULL)
PARSER_PANIC("redefinition of '%s'", tok.data.ident);
+
+ peek_or_panic();
+ if (tok.type == TK_ASSIGN) {
+ expect(TK_ASSIGN);
+ p_node->initial_value = protected_alloc(sizeof(struct expr_node));
+ parse_expr(p_node->initial_value);
+ }
}
static void parse_stmt(struct stmt_node* p_node);
@@ -366,6 +372,25 @@ static void parse_while(struct loop_node* p_node) {
scope_pop(&scope);
}
+static void parse_loop_init(struct loop_init_node* p_node) {
+ peek_or_panic();
+ if (tok.type != TK_IDENT
+ || !scope_get_type(scope, NULL, &(struct type_key) {
+ .name = tok.data.ident,
+ .how_long = 0,
+ .marked_signed = false,
+ .marked_unsigned = false,
+ })) {
+ p_node->type = INIT_EXPR_LIST;
+ p_node->expr_list = protected_alloc(sizeof(struct expr_list_node));
+ parse_expr_list(p_node->expr_list);
+ } else {
+ p_node->type = INIT_DECL;
+ p_node->decl = protected_alloc(sizeof(struct var_decl_node));
+ parse_var_decl(p_node->decl);
+ }
+}
+
static void parse_for(struct loop_node* p_node) {
expect_kw("for");
@@ -375,8 +400,8 @@ static void parse_for(struct loop_node* p_node) {
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);
+ p_node->init = protected_alloc(sizeof(struct loop_init_node));
+ parse_loop_init(p_node->init);
}
expect(TK_SEMI);
peek_or_panic();
@@ -398,30 +423,6 @@ static void parse_for(struct loop_node* p_node) {
scope_pop(&scope);
}
-static void parse_stmt_assign(struct stmt_node* p_node) {
- peek_or_panic();
- if (tok.type != TK_ASSIGN) return;
-
- switch (p_node->type) {
- case STMT_VAR_DECL:
- p_node->inner.expr.inner.assign.lval = (struct lval_node) {
- .type = LVAL_VAR_DECL,
- .inner.var_decl = p_node->inner.var_decl,
- };
- break;
- default:
- return;
- }
-
- p_node->type = STMT_EXPR;
- p_node->inner.expr.type = EXPR_ASSIGN;
- p_node->inner.expr.inner.assign.rval =
- protected_alloc(sizeof(struct expr_node));
-
- expect(TK_ASSIGN);
- parse_expr(p_node->inner.expr.inner.assign.rval);
-}
-
static void parse_stmt(struct stmt_node* p_node) {
peek_or_panic();
switch (tok.type) {
@@ -467,20 +468,20 @@ static void parse_stmt(struct stmt_node* p_node) {
parse_expr(&p_node->inner.expr);
}
- parse_stmt_assign(p_node);
expect(TK_SEMI);
}
-static void parse_args_decl(struct args_decl_node** pp_decl) {
+static void parse_decl_list(struct decl_list_node* p_node) {
for (;;) {
- *pp_decl = protected_alloc(sizeof(struct args_decl_node));
- (*pp_decl)->decl = protected_alloc(sizeof(struct var_decl_node));
- parse_var_decl((*pp_decl)->decl);
- pp_decl = &((*pp_decl)->next);
+ p_node->decl = protected_alloc(sizeof(struct var_decl_node));
+ parse_var_decl(p_node->decl);
peek_or_panic();
- if (tok.type == TK_RPAREN) break;
+ if (tok.type != TK_COMMA) break;
expect(TK_COMMA);
+
+ p_node->next = protected_alloc(sizeof(struct decl_list_node));
+ p_node = p_node->next;
}
}
@@ -509,7 +510,10 @@ static void parse_fn_decl(struct fn_decl_node* p_node) {
p_node->scope = scope;
peek_or_panic();
- if (tok.type != TK_RPAREN) parse_args_decl(&p_node->args);
+ if (tok.type != TK_RPAREN) {
+ p_node->args = protected_alloc(sizeof(struct decl_list_node));
+ parse_decl_list(p_node->args);
+ }
expect(TK_RPAREN);