diff options
Diffstat (limited to 'parser.c')
| -rw-r--r-- | parser.c | 81 |
1 files changed, 58 insertions, 23 deletions
@@ -63,11 +63,14 @@ static void expect_kw(const char* kw) { } static void parse_type(struct type_node* p_node) { - /* TODO: need some concept of known types in scope */ /* TODO: modifiers, void rules, arrays, etc. */ /* TODO: struct, union, enum */ expect(TK_IDENT); - p_node->name = tok.data.ident; + struct type_def type_def; + if (!scope_get_type(scope, &type_def, tok.data.ident)) + PARSER_PANIC("unknown type name: %s", tok.data.ident); + + p_node->def = type_def; peek_or_panic(); p_node->ptr_level = 0; @@ -118,9 +121,6 @@ static void expr_to_lval(struct lval_node* l_node, struct expr_node* e_node) { } static void parse_expr_assign(struct expr_node* p_node) { - peek_or_panic(); - if (tok.type != TK_ASSIGN) return; - expr_to_lval(&p_node->as._assign.lval, p_node); p_node->type = EXPR_ASSIGN; p_node->as._assign.rval = protected_alloc(sizeof(struct expr_node)); @@ -129,6 +129,44 @@ static void parse_expr_assign(struct expr_node* p_node) { parse_expr(p_node->as._assign.rval); } +static void parse_arg_evals(struct expr_node** pp_arg) { + for (;;) { + *pp_arg = protected_alloc(sizeof(struct expr_node)); + parse_expr(*pp_arg); + pp_arg = &((*pp_arg)->next); + + peek_or_panic(); + if (tok.type == TK_RPAREN) break; + expect(TK_COMMA); + } +} + +static void parse_expr_call(struct expr_node* p_node) { + switch (p_node->type) { + case EXPR_VAR_REF: + struct var_def var_def; + if (!scope_get_var(scope, &var_def, p_node->as._var_ref.ident)) + PARSER_PANIC( + "%s is not a known function", p_node->as._var_ref.ident); + + if (var_def.loc.type != STO_FN) + PARSER_PANIC("called object is not a function"); + + p_node->as._call.called_fn = var_def.loc.decl; + break; + default: + PARSER_PANIC("expression is not callable"); + } + + p_node->type = EXPR_CALL; + p_node->as._call.args_head = NULL; + + expect(TK_LPAREN); + peek_or_panic(); + if (tok.type != TK_RPAREN) parse_arg_evals(&p_node->as._call.args_head); + expect(TK_RPAREN); +} + static void parse_expr(struct expr_node* p_node) { peek_or_panic(); switch (tok.type) { @@ -146,27 +184,16 @@ static void parse_expr(struct expr_node* p_node) { case TK_IDENT: p_node->type = EXPR_VAR_REF; parse_var_ref(&p_node->as._var_ref); - - peek_or_panic(); - if (tok.type == TK_ASSIGN) { - p_node->type = EXPR_ASSIGN; - p_node->as._assign = (struct assign_node) { - .lval = { - .type = LVAL_VAR_REF, - .as._var_ref = p_node->as._var_ref, - }, - .rval = protected_alloc(sizeof(struct expr_node)), - }; - - expect(TK_ASSIGN); - parse_expr(p_node->as._assign.rval); - } break; default: PARSER_PANIC("expected expression"); } - parse_expr_assign(p_node); + peek_or_panic(); + if (tok.type == TK_ASSIGN) + parse_expr_assign(p_node); + else if (tok.type == TK_LPAREN) + parse_expr_call(p_node); } static void parse_var_decl(struct var_decl_node* p_node) { @@ -259,7 +286,7 @@ static void parse_stmt(struct stmt_node* p_node) { expect(TK_SEMI); } -static void parse_arg_list(struct var_decl_node** pp_arg) { +static void parse_arg_decls(struct var_decl_node** pp_arg) { for (;;) { *pp_arg = protected_alloc(sizeof(struct var_decl_node)); parse_var_decl(*pp_arg); @@ -280,11 +307,19 @@ static void parse_fn_decl(struct fn_decl_node* p_node) { expect(TK_LPAREN); peek_or_panic(); - if (tok.type != TK_RPAREN) parse_arg_list(&p_node->args_head); + if (tok.type != TK_RPAREN) parse_arg_decls(&p_node->args_head); expect(TK_RPAREN); parse_group(&p_node->body); + + scope_define_var(scope, (struct var_def) { + .name = p_node->name, + .loc = { + .type = STO_FN, + .decl = p_node, + }, + }); } static bool parse_root(struct root_node* p_node) { |
