summaryrefslogtreecommitdiff
path: root/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c104
1 files changed, 66 insertions, 38 deletions
diff --git a/parser.c b/parser.c
index c2eadbe..40d5bbd 100644
--- a/parser.c
+++ b/parser.c
@@ -178,7 +178,7 @@ static void parse_expr_call(struct expr_node* p_node) {
if (var_def->loc.type != STO_FN)
PARSER_PANIC("called object is not a function");
- p_node->inner.call.called_fn_ref = var_def->loc.decl;
+ p_node->inner.call.fn_ref = var_def->loc.decl;
break;
default:
PARSER_PANIC("expression is not callable");
@@ -250,13 +250,19 @@ static void parse_expr_binary(struct expr_node* p_node) {
parse_expr(rhs);
}
+static void parse_paren(struct paren_node* p_node) {
+ expect(TK_LPAREN);
+ p_node->expr_list = ccc_alloc(sizeof(struct expr_list_node));
+ parse_expr_list(p_node->expr_list);
+ expect(TK_RPAREN);
+}
+
static void parse_expr(struct expr_node* p_node) {
peek_or_panic();
switch (tok.type) {
case TK_LPAREN:
- expect(TK_LPAREN);
- parse_expr(p_node);
- expect(TK_RPAREN);
+ p_node->type = EXPR_PAREN;
+ parse_paren(&p_node->inner.paren);
break;
case TK_NEG:
p_node->type = EXPR_UNARY;
@@ -294,23 +300,38 @@ static void parse_expr(struct expr_node* p_node) {
}
}
-static void parse_var_decl(struct var_decl_node* p_node) {
- parse_type_ref(&p_node->type);
+static void parse_decl(const struct type* type, struct decl_node* p_node) {
expect(TK_IDENT);
-
p_node->def_ref = scope_define_var(scope, (struct var_def) {
- .type = &p_node->type,
+ .type = type,
.name = tok.data.ident,
.loc.type = STO_UNRESOLVED,
});
if (p_node->def_ref == NULL)
- PARSER_PANIC("redefinition of '%s'", tok.data.ident);
+ PARSER_PANIC("redefinition of '%s' in same scope", tok.data.ident);
peek_or_panic();
if (tok.type == TK_ASSIGN) {
expect(TK_ASSIGN);
p_node->initial_value = ccc_alloc(sizeof(struct expr_node));
parse_expr(p_node->initial_value);
+ peek_or_panic();
+ }
+
+ if (tok.type == TK_COMMA) {
+ expect(TK_COMMA);
+ p_node->next = ccc_alloc(sizeof(struct decl_node));
+ parse_decl(type, p_node->next);
+ }
+}
+
+static void parse_decl_list(struct decl_list_node* p_node) {
+ parse_type_ref(&p_node->type);
+
+ peek_or_panic();
+ if (tok.type == TK_IDENT) {
+ p_node->head = ccc_alloc(sizeof(struct decl_node));
+ parse_decl(&p_node->type, p_node->head);
}
}
@@ -325,8 +346,8 @@ static void parse_return(struct return_node* p_node) {
return;
}
- p_node->ret_val = ccc_alloc(sizeof(struct expr_node));
- parse_expr(p_node->ret_val);
+ p_node->ret_val = ccc_alloc(sizeof(struct expr_list_node));
+ parse_expr_list(p_node->ret_val);
}
static void parse_group(struct group_node* p_node) {
@@ -357,8 +378,8 @@ static void parse_if(struct if_node* p_node) {
p_node->scope = scope;
expect(TK_LPAREN);
- p_node->cond = ccc_alloc(sizeof(struct expr_node));
- parse_expr(p_node->cond);
+ p_node->cond = ccc_alloc(sizeof(struct expr_list_node));
+ parse_expr_list(p_node->cond);
expect(TK_RPAREN);
p_node->true_branch = ccc_alloc(sizeof(struct stmt_node));
@@ -382,8 +403,8 @@ static void parse_while(struct loop_node* p_node) {
p_node->scope = scope;
expect(TK_LPAREN);
- p_node->cond = ccc_alloc(sizeof(struct expr_node));
- parse_expr(p_node->cond);
+ p_node->cond = ccc_alloc(sizeof(struct expr_list_node));
+ parse_expr_list(p_node->cond);
expect(TK_RPAREN);
p_node->body = ccc_alloc(sizeof(struct stmt_node));
@@ -406,14 +427,14 @@ static bool is_type_token() {
static void parse_loop_init(struct loop_init_node* p_node) {
peek_or_panic();
- if (!is_type_token()) {
+ if (is_type_token()) {
+ p_node->type = INIT_DECL_LIST;
+ p_node->decl_list = ccc_alloc(sizeof(struct decl_list_node));
+ parse_decl_list(p_node->decl_list);
+ } else {
p_node->type = INIT_EXPR_LIST;
p_node->expr_list = ccc_alloc(sizeof(struct expr_list_node));
parse_expr_list(p_node->expr_list);
- } else {
- p_node->type = INIT_DECL;
- p_node->decl = ccc_alloc(sizeof(struct var_decl_node));
- parse_var_decl(p_node->decl);
}
}
@@ -432,14 +453,14 @@ static void parse_for(struct loop_node* p_node) {
expect(TK_SEMI);
peek_or_panic();
if (tok.type != TK_SEMI) {
- p_node->cond = ccc_alloc(sizeof(struct expr_node));
- parse_expr(p_node->cond);
+ p_node->cond = ccc_alloc(sizeof(struct expr_list_node));
+ parse_expr_list(p_node->cond);
}
expect(TK_SEMI);
peek_or_panic();
if (tok.type != TK_RPAREN) {
- p_node->incr = ccc_alloc(sizeof(struct expr_node));
- parse_expr(p_node->incr);
+ p_node->incr = ccc_alloc(sizeof(struct expr_list_node));
+ parse_expr_list(p_node->incr);
}
expect(TK_RPAREN);
@@ -477,29 +498,36 @@ static void parse_stmt(struct stmt_node* p_node) {
parse_return(&p_node->inner.return_);
break;
} else if (is_type_token()) {
- p_node->type = STMT_VAR_DECL;
- parse_var_decl(&p_node->inner.var_decl);
+ p_node->type = STMT_DECL_LIST;
+ parse_decl_list(&p_node->inner.decl_list);
break;
}
default:
- p_node->type = STMT_EXPR;
- parse_expr(&p_node->inner.expr);
+ p_node->type = STMT_EXPR_LIST;
+ parse_expr_list(&p_node->inner.expr_list);
}
expect(TK_SEMI);
}
-static void parse_decl_list(struct decl_list_node* p_node) {
- for (;;) {
- p_node->decl = ccc_alloc(sizeof(struct var_decl_node));
- parse_var_decl(p_node->decl);
+static void parse_fn_arg(struct arg_decl_node* p_node) {
+ parse_type_ref(&p_node->type);
- peek_or_panic();
- if (tok.type != TK_COMMA) break;
+ expect(TK_IDENT);
+ p_node->def_ref = scope_define_var(scope, (struct var_def) {
+ .type = &p_node->type,
+ .name = tok.data.ident,
+ .loc.type = STO_UNRESOLVED,
+ });
+ if (p_node->def_ref == NULL)
+ PARSER_PANIC("redefinition of parameter '%s'", tok.data.ident);
+
+ peek_or_panic();
+ if (tok.type == TK_COMMA) {
expect(TK_COMMA);
- p_node->next = ccc_alloc(sizeof(struct decl_list_node));
- p_node = p_node->next;
+ p_node->next = ccc_alloc(sizeof(struct arg_decl_node));
+ parse_fn_arg(p_node->next);
}
}
@@ -529,8 +557,8 @@ static void parse_fn_decl(struct fn_decl_node* p_node) {
peek_or_panic();
if (tok.type != TK_RPAREN) {
- p_node->args = ccc_alloc(sizeof(struct decl_list_node));
- parse_decl_list(p_node->args);
+ p_node->args = ccc_alloc(sizeof(struct arg_decl_node));
+ parse_fn_arg(p_node->args);
}
expect(TK_RPAREN);