diff options
Diffstat (limited to 'parser.c')
| -rw-r--r-- | parser.c | 53 |
1 files changed, 42 insertions, 11 deletions
@@ -1,5 +1,6 @@ #include "parser.h" #include "lexer.h" +#include "scope.h" #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -16,6 +17,7 @@ } static struct token tok; +static struct scope* scope; static void* protected_alloc(size_t sz) { void* ptr = calloc(1, sz); @@ -38,14 +40,27 @@ static void expect(enum token_type expected) { if (tok.type != expected) unexpected_token(expected); } +static void peek_or_panic() { + if (!lexer_peek(&tok)) + PARSER_PANIC("unexpected EOF"); +} + /* "handle" indicates that we've peeked already */ static void handle_expr(struct expr_node* p_node); static void handle_stmt(struct stmt_node* p_node); -static void parse_type(struct type_node* p_node) { - expect(TK_IDENT); - /* TODO: maybe check that this type is real haha */ - p_node->type = tok.data.ident; +static void handle_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 */ + p_node->name = tok.data.ident; + + peek_or_panic(); + p_node->ptr_level = 0; + while (tok.type == TK_STAR) { + p_node->ptr_level++; + expect(TK_STAR); + } } static void parse_return(struct return_node* p_node) { @@ -70,6 +85,11 @@ static void parse_int_lit(struct int_lit_node* p_node) { p_node->val = tok.data.int_lit; } +static void parse_var_ref(struct var_ref_node* p_node) { + expect(TK_IDENT); + p_node->ident = tok.data.ident; +} + static void handle_expr(struct expr_node* p_node) { switch (tok.type) { case TK_SEMI: @@ -79,13 +99,17 @@ static void handle_expr(struct expr_node* p_node) { p_node->type = EXPR_INT_LIT; parse_int_lit(&p_node->as._int_lit); return; + case TK_IDENT: + p_node->type = EXPR_VAR_REF; + parse_var_ref(&p_node->as._var_ref); + return; default: PARSER_PANIC("expected expression"); } } -static void parse_var_decl(struct var_decl_node* p_node) { - parse_type(&p_node->type); +static void handle_var_decl(struct var_decl_node* p_node) { + handle_type(&p_node->type); expect(TK_IDENT); p_node->ident = tok.data.ident; } @@ -118,11 +142,12 @@ static void handle_stmt(struct stmt_node* p_node) { if (strcmp(tok.data.ident, "return") == 0) { p_node->type = STMT_RETURN; parse_return(&p_node->as._return); - } else { + break; + } else if (scope_get_type(scope, NULL, tok.data.ident)) { p_node->type = STMT_VAR_DECL; - parse_var_decl(&p_node->as._var_decl); + handle_var_decl(&p_node->as._var_decl); + break; } - break; default: p_node->type = STMT_EXPR; handle_expr(&p_node->as._expr); @@ -132,8 +157,10 @@ static void handle_stmt(struct stmt_node* p_node) { static void parse_arg_list(struct var_decl_node** pp_arg) { for (;;) { + expect(TK_IDENT); + *pp_arg = protected_alloc(sizeof(struct var_decl_node)); - parse_var_decl(*pp_arg); + handle_var_decl(*pp_arg); pp_arg = &((*pp_arg)->next); if (!lexer_peek(&tok)) @@ -145,7 +172,8 @@ static void parse_arg_list(struct var_decl_node** pp_arg) { } static void parse_fn_decl(struct fn_decl_node* p_node) { - parse_type(&p_node->return_type); + expect(TK_IDENT); + handle_type(&p_node->return_type); expect(TK_IDENT); p_node->name = tok.data.ident; @@ -173,6 +201,8 @@ static bool parse_root(struct root_node* p_node) { struct root_node* parse(const char* path) { lexer_load(path); + scope_push(&scope); + scope_install_default_types(scope); struct root_node* root; struct root_node** p_node = &root; @@ -187,6 +217,7 @@ struct root_node* parse(const char* path) { p_node = &((*p_node)->next); } + scope_pop(&scope); lexer_close(); return root; } |
