diff options
| author | gingerBill <ginger.bill.22@gmail.com> | 2016-07-21 00:26:14 +0100 |
|---|---|---|
| committer | gingerBill <ginger.bill.22@gmail.com> | 2016-07-21 00:26:14 +0100 |
| commit | cbd82e3c02cbeff8fe3ba5198d6ca730f8c1eace (patch) | |
| tree | 00728d59925609e8fd081f5276e8b26117ec00e3 /src/parser.cpp | |
| parent | aa6a2caecb759522914ba82cc506e60270ad1ab0 (diff) | |
Support import files as modules (i.e. import only once)
Diffstat (limited to 'src/parser.cpp')
| -rw-r--r-- | src/parser.cpp | 1181 |
1 files changed, 670 insertions, 511 deletions
diff --git a/src/parser.cpp b/src/parser.cpp index 050a69894..223229f03 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2,6 +2,27 @@ struct AstNode; struct Type; struct AstScope; + + +struct AstFile { + gbArena arena; + Tokenizer tokenizer; + gbArray(Token) tokens; + Token * cursor; // NOTE(bill): Current token, easy to peek forward and backwards if needed + + AstNode *declarations; + isize declaration_count; + + AstScope *file_scope; + AstScope *curr_scope; + isize scope_level; + + isize error_count; + isize error_prev_line; + isize error_prev_column; +}; + + // NOTE(bill): Just used to quickly check if there is double declaration in the same scope // No type checking actually happens // TODO(bill): Should this be completely handled in the semantic checker or is it better here? @@ -17,19 +38,9 @@ struct AstScope { }; struct Parser { - gbArena arena; - Tokenizer tokenizer; - gbArray(Token) tokens; - Token * cursor; // NOTE(bill): Current token, easy to peek forward and backwards if needed - - AstScope *file_scope; - AstScope *curr_scope; - isize scope_level; - -#define MAX_PARSER_ERROR_COUNT 10 - isize error_count; - isize error_prev_line; - isize error_prev_column; + gbArray(AstFile) files; + gbArray(String) imports; + isize import_index; }; enum AstNodeKind { @@ -75,6 +86,7 @@ AstNode__DeclarationBegin, AstNode_VariableDeclaration, AstNode_ProcedureDeclaration, AstNode_TypeDeclaration, + AstNode_ImportDeclaration, AstNode__DeclarationEnd, AstNode__TypeBegin, @@ -207,6 +219,10 @@ struct AstNode { AstNode *name; // AstNode_Identifier AstNode *type_expression; } type_declaration; + struct { + Token token; + Token filepath; + } import_declaration; struct { @@ -226,9 +242,8 @@ struct AstNode { }; }; - -gb_inline AstScope *make_ast_scope(Parser *p, AstScope *parent) { - AstScope *scope = gb_alloc_item(gb_arena_allocator(&p->arena), AstScope); +gb_inline AstScope *make_ast_scope(AstFile *f, AstScope *parent) { + AstScope *scope = gb_alloc_item(gb_arena_allocator(&f->arena), AstScope); map_init(&scope->entities, gb_heap_allocator()); scope->parent = parent; return scope; @@ -310,6 +325,8 @@ Token ast_node_token(AstNode *node) { return node->procedure_declaration.name->identifier.token; case AstNode_TypeDeclaration: return node->type_declaration.token; + case AstNode_ImportDeclaration: + return node->import_declaration.token; case AstNode_Field: { if (node->field.name_list) return ast_node_token(node->field.name_list); @@ -336,28 +353,28 @@ gb_inline void destroy_ast_scope(AstScope *scope) { map_destroy(&scope->entities); } -gb_inline AstScope *open_ast_scope(Parser *p) { - AstScope *scope = make_ast_scope(p, p->curr_scope); - p->curr_scope = scope; - p->scope_level++; - return p->curr_scope; +gb_inline AstScope *open_ast_scope(AstFile *f) { + AstScope *scope = make_ast_scope(f, f->curr_scope); + f->curr_scope = scope; + f->scope_level++; + return f->curr_scope; } -gb_inline void close_ast_scope(Parser *p) { - GB_ASSERT_NOT_NULL(p->curr_scope); - GB_ASSERT(p->scope_level > 0); +gb_inline void close_ast_scope(AstFile *f) { + GB_ASSERT_NOT_NULL(f->curr_scope); + GB_ASSERT(f->scope_level > 0); { - AstScope *parent = p->curr_scope->parent; - if (p->curr_scope) { - destroy_ast_scope(p->curr_scope); + AstScope *parent = f->curr_scope->parent; + if (f->curr_scope) { + destroy_ast_scope(f->curr_scope); } - p->curr_scope = parent; - p->scope_level--; + f->curr_scope = parent; + f->scope_level--; } } -AstEntity *make_ast_entity(Parser *p, Token token, AstNode *declaration, AstScope *parent) { - AstEntity *entity = gb_alloc_item(gb_arena_allocator(&p->arena), AstEntity); +AstEntity *make_ast_entity(AstFile *f, Token token, AstNode *declaration, AstScope *parent) { + AstEntity *entity = gb_alloc_item(gb_arena_allocator(&f->arena), AstEntity); entity->token = token; entity->declaration = declaration; entity->parent = parent; @@ -381,88 +398,99 @@ AstEntity *ast_scope_insert(AstScope *scope, AstEntity entity) { } -#define print_parse_error(p, token, fmt, ...) print_parse_error_(p, __FUNCTION__, token, fmt, ##__VA_ARGS__) -void print_parse_error_(Parser *p, char *function, Token token, char *fmt, ...) { - +#define ast_file_err(f, token, fmt, ...) ast_file_err_(f, __FUNCTION__, token, fmt, ##__VA_ARGS__) +void ast_file_err_(AstFile *file, char *function, Token token, char *fmt, ...) { // NOTE(bill): Duplicate error, skip it - if (p->error_prev_line != token.line || p->error_prev_column != token.column) { + if (file->error_prev_line != token.line || file->error_prev_column != token.column) { va_list va; - p->error_prev_line = token.line; - p->error_prev_column = token.column; + file->error_prev_line = token.line; + file->error_prev_column = token.column; - #if 1 + #if 0 gb_printf_err("%s()\n", function); #endif va_start(va, fmt); - gb_printf_err("%s(%td:%td) Syntax error: %s\n", - p->tokenizer.fullpath, token.line, token.column, + gb_printf_err("%.*s(%td:%td) Syntax error: %s\n", + LIT(file->tokenizer.fullpath), token.line, token.column, gb_bprintf_va(fmt, va)); va_end(va); } - p->error_count++; + file->error_count++; } // NOTE(bill): And this below is why is I/we need a new language! Discriminated unions are a pain in C/C++ -gb_inline AstNode *make_node(Parser *p, AstNodeKind kind) { - if (gb_arena_size_remaining(&p->arena, GB_DEFAULT_MEMORY_ALIGNMENT) < gb_size_of(AstNode)) { +gb_inline AstNode *make_node(AstFile *f, AstNodeKind kind) { + gbArena *arena = &f->arena; + if (gb_arena_size_remaining(arena, GB_DEFAULT_MEMORY_ALIGNMENT) < gb_size_of(AstNode)) { // NOTE(bill): If a syntax error is so bad, just quit! gb_exit(1); } - AstNode *node = gb_alloc_item(gb_arena_allocator(&p->arena), AstNode); + AstNode *node = gb_alloc_item(gb_arena_allocator(arena), AstNode); node->kind = kind; return node; } -gb_inline AstNode *make_bad_expression(Parser *p, Token begin, Token end) { - AstNode *result = make_node(p, AstNode_BadExpression); +gb_inline AstNode *make_bad_expression(AstFile *f, Token begin, Token end) { + AstNode *result = make_node(f, AstNode_BadExpression); result->bad_expression.begin = begin; result->bad_expression.end = end; return result; } -gb_inline AstNode *make_tag_expression(Parser *p, Token token, Token name, AstNode *expression) { - AstNode *result = make_node(p, AstNode_TagExpression); +gb_inline AstNode *make_tag_expression(AstFile *f, Token token, Token name, AstNode *expression) { + AstNode *result = make_node(f, AstNode_TagExpression); result->tag_expression.token = token; result->tag_expression.name = name; result->tag_expression.expression = expression; return result; } -gb_inline AstNode *make_tag_statement(Parser *p, Token token, Token name, AstNode *statement) { - AstNode *result = make_node(p, AstNode_TagStatement); +gb_inline AstNode *make_tag_statement(AstFile *f, Token token, Token name, AstNode *statement) { + AstNode *result = make_node(f, AstNode_TagStatement); result->tag_statement.token = token; result->tag_statement.name = name; result->tag_statement.statement = statement; return result; } -gb_inline AstNode *make_unary_expression(Parser *p, Token op, AstNode *operand) { - AstNode *result = make_node(p, AstNode_UnaryExpression); +gb_inline AstNode *make_unary_expression(AstFile *f, Token op, AstNode *operand) { + AstNode *result = make_node(f, AstNode_UnaryExpression); result->unary_expression.op = op; result->unary_expression.operand = operand; return result; } -gb_inline AstNode *make_binary_expression(Parser *p, Token op, AstNode *left, AstNode *right) { - AstNode *result = make_node(p, AstNode_BinaryExpression); +gb_inline AstNode *make_binary_expression(AstFile *f, Token op, AstNode *left, AstNode *right) { + AstNode *result = make_node(f, AstNode_BinaryExpression); + + if (left == NULL) { + ast_file_err(f, op, "No lhs expression for binary expression `%.*s`", LIT(op.string)); + left = make_bad_expression(f, op, op); + } + if (right == NULL) { + ast_file_err(f, op, "No rhs expression for binary expression `%.*s`", LIT(op.string)); + right = make_bad_expression(f, op, op); + } + result->binary_expression.op = op; result->binary_expression.left = left; result->binary_expression.right = right; + return result; } -gb_inline AstNode *make_paren_expression(Parser *p, AstNode *expression, Token open, Token close) { - AstNode *result = make_node(p, AstNode_ParenExpression); +gb_inline AstNode *make_paren_expression(AstFile *f, AstNode *expression, Token open, Token close) { + AstNode *result = make_node(f, AstNode_ParenExpression); result->paren_expression.expression = expression; result->paren_expression.open = open; result->paren_expression.close = close; return result; } -gb_inline AstNode *make_call_expression(Parser *p, AstNode *proc, AstNode *arg_list, isize arg_list_count, Token open, Token close) { - AstNode *result = make_node(p, AstNode_CallExpression); +gb_inline AstNode *make_call_expression(AstFile *f, AstNode *proc, AstNode *arg_list, isize arg_list_count, Token open, Token close) { + AstNode *result = make_node(f, AstNode_CallExpression); result->call_expression.proc = proc; result->call_expression.arg_list = arg_list; result->call_expression.arg_list_count = arg_list_count; @@ -471,15 +499,15 @@ gb_inline AstNode *make_call_expression(Parser *p, AstNode *proc, AstNode *arg_l return result; } -gb_inline AstNode *make_selector_expression(Parser *p, Token token, AstNode *operand, AstNode *selector) { - AstNode *result = make_node(p, AstNode_SelectorExpression); +gb_inline AstNode *make_selector_expression(AstFile *f, Token token, AstNode *operand, AstNode *selector) { + AstNode *result = make_node(f, AstNode_SelectorExpression); result->selector_expression.operand = operand; result->selector_expression.selector = selector; return result; } -gb_inline AstNode *make_index_expression(Parser *p, AstNode *expression, AstNode *value, Token open, Token close) { - AstNode *result = make_node(p, AstNode_IndexExpression); +gb_inline AstNode *make_index_expression(AstFile *f, AstNode *expression, AstNode *value, Token open, Token close) { + AstNode *result = make_node(f, AstNode_IndexExpression); result->index_expression.expression = expression; result->index_expression.value = value; result->index_expression.open = open; @@ -488,8 +516,8 @@ gb_inline AstNode *make_index_expression(Parser *p, AstNode *expression, AstNode } -gb_inline AstNode *make_slice_expression(Parser *p, AstNode *expression, Token open, Token close, AstNode *low, AstNode *high, AstNode *max, b32 triple_indexed) { - AstNode *result = make_node(p, AstNode_SliceExpression); +gb_inline AstNode *make_slice_expression(AstFile *f, AstNode *expression, Token open, Token close, AstNode *low, AstNode *high, AstNode *max, b32 triple_indexed) { + AstNode *result = make_node(f, AstNode_SliceExpression); result->slice_expression.expression = expression; result->slice_expression.open = open; result->slice_expression.close = close; @@ -500,8 +528,8 @@ gb_inline AstNode *make_slice_expression(Parser *p, AstNode *expression, Token o return result; } -gb_inline AstNode *make_cast_expression(Parser *p, Token token, AstNode *type_expression, AstNode *operand) { - AstNode *result = make_node(p, AstNode_CastExpression); +gb_inline AstNode *make_cast_expression(AstFile *f, Token token, AstNode *type_expression, AstNode *operand) { + AstNode *result = make_node(f, AstNode_CastExpression); result->cast_expression.token = token; result->cast_expression.type_expression = type_expression; result->cast_expression.operand = operand; @@ -509,55 +537,55 @@ gb_inline AstNode *make_cast_expression(Parser *p, Token token, AstNode *type_ex } -gb_inline AstNode *make_dereference_expression(Parser *p, AstNode *operand, Token op) { - AstNode *result = make_node(p, AstNode_DereferenceExpression); +gb_inline AstNode *make_dereference_expression(AstFile *f, AstNode *operand, Token op) { + AstNode *result = make_node(f, AstNode_DereferenceExpression); result->dereference_expression.operand = operand; result->dereference_expression.op = op; return result; } -gb_inline AstNode *make_basic_literal(Parser *p, Token basic_literal) { - AstNode *result = make_node(p, AstNode_BasicLiteral); +gb_inline AstNode *make_basic_literal(AstFile *f, Token basic_literal) { + AstNode *result = make_node(f, AstNode_BasicLiteral); result->basic_literal = basic_literal; return result; } -gb_inline AstNode *make_identifier(Parser *p, Token token, AstEntity *entity = NULL) { - AstNode *result = make_node(p, AstNode_Identifier); +gb_inline AstNode *make_identifier(AstFile *f, Token token, AstEntity *entity = NULL) { + AstNode *result = make_node(f, AstNode_Identifier); result->identifier.token = token; result->identifier.entity = entity; return result; } -gb_inline AstNode *make_bad_statement(Parser *p, Token begin, Token end) { - AstNode *result = make_node(p, AstNode_BadStatement); +gb_inline AstNode *make_bad_statement(AstFile *f, Token begin, Token end) { + AstNode *result = make_node(f, AstNode_BadStatement); result->bad_statement.begin = begin; result->bad_statement.end = end; return result; } -gb_inline AstNode *make_empty_statement(Parser *p, Token token) { - AstNode *result = make_node(p, AstNode_EmptyStatement); +gb_inline AstNode *make_empty_statement(AstFile *f, Token token) { + AstNode *result = make_node(f, AstNode_EmptyStatement); result->empty_statement.token = token; return result; } -gb_inline AstNode *make_expression_statement(Parser *p, AstNode *expression) { - AstNode *result = make_node(p, AstNode_ExpressionStatement); +gb_inline AstNode *make_expression_statement(AstFile *f, AstNode *expression) { + AstNode *result = make_node(f, AstNode_ExpressionStatement); result->expression_statement.expression = expression; return result; } -gb_inline AstNode *make_inc_dec_statement(Parser *p, Token op, AstNode *expression) { - AstNode *result = make_node(p, AstNode_IncDecStatement); +gb_inline AstNode *make_inc_dec_statement(AstFile *f, Token op, AstNode *expression) { + AstNode *result = make_node(f, AstNode_IncDecStatement); result->inc_dec_statement.op = op; result->inc_dec_statement.expression = expression; return result; } -gb_inline AstNode *make_assign_statement(Parser *p, Token op, AstNode *lhs_list, isize lhs_count, AstNode *rhs_list, isize rhs_count) { - AstNode *result = make_node(p, AstNode_AssignStatement); +gb_inline AstNode *make_assign_statement(AstFile *f, Token op, AstNode *lhs_list, isize lhs_count, AstNode *rhs_list, isize rhs_count) { + AstNode *result = make_node(f, AstNode_AssignStatement); result->assign_statement.op = op; result->assign_statement.lhs_list = lhs_list; result->assign_statement.lhs_count = lhs_count; @@ -566,8 +594,8 @@ gb_inline AstNode *make_assign_statement(Parser *p, Token op, AstNode *lhs_list, return result; } -gb_inline AstNode *make_block_statement(Parser *p, AstNode *list, isize list_count, Token open, Token close) { - AstNode *result = make_node(p, AstNode_BlockStatement); +gb_inline AstNode *make_block_statement(AstFile *f, AstNode *list, isize list_count, Token open, Token close) { + AstNode *result = make_node(f, AstNode_BlockStatement); result->block_statement.list = list; result->block_statement.list_count = list_count; result->block_statement.open = open; @@ -575,8 +603,8 @@ gb_inline AstNode *make_block_statement(Parser *p, AstNode *list, isize list_cou return result; } -gb_inline AstNode *make_if_statement(Parser *p, Token token, AstNode *cond, AstNode *body, AstNode *else_statement) { - AstNode *result = make_node(p, AstNode_IfStatement); +gb_inline AstNode *make_if_statement(AstFile *f, Token token, AstNode *cond, AstNode *body, AstNode *else_statement) { + AstNode *result = make_node(f, AstNode_IfStatement); result->if_statement.token = token; result->if_statement.cond = cond; result->if_statement.body = body; @@ -584,16 +612,16 @@ gb_inline AstNode *make_if_statement(Parser *p, Token token, AstNode *cond, AstN return result; } -gb_inline AstNode *make_return_statement(Parser *p, Token token, AstNode *results, isize result_count) { - AstNode *result = make_node(p, AstNode_ReturnStatement); +gb_inline AstNode *make_return_statement(AstFile *f, Token token, AstNode *results, isize result_count) { + AstNode *result = make_node(f, AstNode_ReturnStatement); result->return_statement.token = token; result->return_statement.results = results; result->return_statement.result_count = result_count; return result; } -gb_inline AstNode *make_for_statement(Parser *p, Token token, AstNode *init, AstNode *cond, AstNode *end, AstNode *body) { - AstNode *result = make_node(p, AstNode_ForStatement); +gb_inline AstNode *make_for_statement(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *end, AstNode *body) { + AstNode *result = make_node(f, AstNode_ForStatement); result->for_statement.token = token; result->for_statement.init = init; result->for_statement.cond = cond; @@ -601,22 +629,22 @@ gb_inline AstNode *make_for_statement(Parser *p, Token token, AstNode *init, Ast result->for_statement.body = body; return result; } -gb_inline AstNode *make_defer_statement(Parser *p, Token token, AstNode *statement) { - AstNode *result = make_node(p, AstNode_DeferStatement); +gb_inline AstNode *make_defer_statement(AstFile *f, Token token, AstNode *statement) { + AstNode *result = make_node(f, AstNode_DeferStatement); result->defer_statement.token = token; result->defer_statement.statement = statement; return result; } -gb_inline AstNode *make_bad_declaration(Parser *p, Token begin, Token end) { - AstNode *result = make_node(p, AstNode_BadDeclaration); +gb_inline AstNode *make_bad_declaration(AstFile *f, Token begin, Token end) { + AstNode *result = make_node(f, AstNode_BadDeclaration); result->bad_declaration.begin = begin; result->bad_declaration.end = end; return result; } -gb_inline AstNode *make_variable_declaration(Parser *p, DeclarationKind kind, AstNode *name_list, isize name_list_count, AstNode *type_expression, AstNode *value_list, isize value_list_count) { - AstNode *result = make_node(p, AstNode_VariableDeclaration); +gb_inline AstNode *make_variable_declaration(AstFile *f, DeclarationKind kind, AstNode *name_list, isize name_list_count, AstNode *type_expression, AstNode *value_list, isize value_list_count) { + AstNode *result = make_node(f, AstNode_VariableDeclaration); result->variable_declaration.kind = kind; result->variable_declaration.name_list = name_list; result->variable_declaration.name_list_count = name_list_count; @@ -626,16 +654,16 @@ gb_inline AstNode *make_variable_declaration(Parser *p, DeclarationKind kind, As return result; } -gb_inline AstNode *make_field(Parser *p, AstNode *name_list, isize name_list_count, AstNode *type_expression) { - AstNode *result = make_node(p, AstNode_Field); +gb_inline AstNode *make_field(AstFile *f, AstNode *name_list, isize name_list_count, AstNode *type_expression) { + AstNode *result = make_node(f, AstNode_Field); result->field.name_list = name_list; result->field.name_list_count = name_list_count; result->field.type_expression = type_expression; return result; } -gb_inline AstNode *make_procedure_type(Parser *p, Token token, AstNode *param_list, isize param_count, AstNode *results_list, isize result_count) { - AstNode *result = make_node(p, AstNode_ProcedureType); +gb_inline AstNode *make_procedure_type(AstFile *f, Token token, AstNode *param_list, isize param_count, AstNode *results_list, isize result_count) { + AstNode *result = make_node(f, AstNode_ProcedureType); result->procedure_type.token = token; result->procedure_type.param_list = param_list; result->procedure_type.param_count = param_count; @@ -644,8 +672,8 @@ gb_inline AstNode *make_procedure_type(Parser *p, Token token, AstNode *param_li return result; } -gb_inline AstNode *make_procedure_declaration(Parser *p, DeclarationKind kind, AstNode *name, AstNode *procedure_type, AstNode *body, AstNode *tag_list, isize tag_count) { - AstNode *result = make_node(p, AstNode_ProcedureDeclaration); +gb_inline AstNode *make_procedure_declaration(AstFile *f, DeclarationKind kind, AstNode *name, AstNode *procedure_type, AstNode *body, AstNode *tag_list, isize tag_count) { + AstNode *result = make_node(f, AstNode_ProcedureDeclaration); result->procedure_declaration.kind = kind; result->procedure_declaration.name = name; result->procedure_declaration.procedure_type = procedure_type; @@ -655,81 +683,90 @@ gb_inline AstNode *make_procedure_declaration(Parser *p, DeclarationKind kind, A return result; } -gb_inline AstNode *make_pointer_type(Parser *p, Token token, AstNode *type_expression) { - AstNode *result = make_node(p, AstNode_PointerType); +gb_inline AstNode *make_pointer_type(AstFile *f, Token token, AstNode *type_expression) { + AstNode *result = make_node(f, AstNode_PointerType); result->pointer_type.token = token; result->pointer_type.type_expression = type_expression; return result; } -gb_inline AstNode *make_array_type(Parser *p, Token token, AstNode *count, AstNode *element) { - AstNode *result = make_node(p, AstNode_ArrayType); +gb_inline AstNode *make_array_type(AstFile *f, Token token, AstNode *count, AstNode *element) { + AstNode *result = make_node(f, AstNode_ArrayType); result->array_type.token = token; result->array_type.count = count; result->array_type.element = element; return result; } -gb_inline AstNode *make_struct_type(Parser *p, Token token, AstNode *field_list, isize field_count) { - AstNode *result = make_node(p, AstNode_StructType); +gb_inline AstNode *make_struct_type(AstFile *f, Token token, AstNode *field_list, isize field_count) { + AstNode *result = make_node(f, AstNode_StructType); result->struct_type.token = token; result->struct_type.field_list = field_list; result->struct_type.field_count = field_count; return result; } -gb_inline AstNode *make_type_declaration(Parser *p, Token token, AstNode *name, AstNode *type_expression) { - AstNode *result = make_node(p, AstNode_TypeDeclaration); +gb_inline AstNode *make_type_declaration(AstFile *f, Token token, AstNode *name, AstNode *type_expression) { + AstNode *result = make_node(f, AstNode_TypeDeclaration); result->type_declaration.token = token; result->type_declaration.name = name; result->type_declaration.type_expression = type_expression; return result; } +gb_inline AstNode *make_import_declaration(AstFile *f, Token token, Token filepath) { + AstNode *result = make_node(f, AstNode_ImportDeclaration); + result->import_declaration.token = token; + result->import_declaration.filepath = filepath; + return result; +} -gb_inline b32 next_token(Parser *p) { - if (p->cursor+1 < p->tokens + gb_array_count(p->tokens)) { - p->cursor++; +gb_inline b32 next_token(AstFile *f) { + if (f->cursor+1 < f->tokens + gb_array_count(f->tokens)) { + f->cursor++; return true; } else { - print_parse_error(p, p->cursor[0], "Token is EOF"); + ast_file_err(f, f->cursor[0], "Token is EOF"); return false; } } -gb_inline Token expect_token(Parser *p, TokenKind kind) { - Token prev = p->cursor[0]; - if (prev.kind != kind) - print_parse_error(p, p->cursor[0], "Expected `%s`, got `%s`", - token_kind_to_string(kind), - token_kind_to_string(prev.kind)); - next_token(p); +gb_inline Token expect_token(AstFile *f, TokenKind kind) { + Token prev = f->cursor[0]; + if (prev.kind != kind) { + ast_file_err(f, f->cursor[0], "Expected `%s`, got `%s`", + token_kind_to_string(kind), + token_kind_to_string(prev.kind)); + } + next_token(f); return prev; } -gb_inline Token expect_operator(Parser *p) { - Token prev = p->cursor[0]; - if (!gb_is_between(prev.kind, Token__OperatorBegin+1, Token__OperatorEnd-1)) - print_parse_error(p, p->cursor[0], "Expected an operator, got `%s`", - token_kind_to_string(prev.kind)); - next_token(p); +gb_inline Token expect_operator(AstFile *f) { + Token prev = f->cursor[0]; + if (!gb_is_between(prev.kind, Token__OperatorBegin+1, Token__OperatorEnd-1)) { + ast_file_err(f, f->cursor[0], "Expected an operator, got `%s`", + token_kind_to_string(prev.kind)); + } + next_token(f); return prev; } -gb_inline Token expect_keyword(Parser *p) { - Token prev = p->cursor[0]; - if (!gb_is_between(prev.kind, Token__KeywordBegin+1, Token__KeywordEnd-1)) - print_parse_error(p, p->cursor[0], "Expected a keyword, got `%s`", - token_kind_to_string(prev.kind)); - next_token(p); +gb_inline Token expect_keyword(AstFile *f) { + Token prev = f->cursor[0]; + if (!gb_is_between(prev.kind, Token__KeywordBegin+1, Token__KeywordEnd-1)) { + ast_file_err(f, f->cursor[0], "Expected a keyword, got `%s`", + token_kind_to_string(prev.kind)); + } + next_token(f); return prev; } -gb_inline b32 allow_token(Parser *p, TokenKind kind) { - Token prev = p->cursor[0]; +gb_inline b32 allow_token(AstFile *f, TokenKind kind) { + Token prev = f->cursor[0]; if (prev.kind == kind) { - next_token(p); + next_token(f); return true; } return false; @@ -737,87 +774,52 @@ gb_inline b32 allow_token(Parser *p, TokenKind kind) { -b32 init_parser(Parser *p, char *filename) { - if (init_tokenizer(&p->tokenizer, filename)) { - gb_array_init(p->tokens, gb_heap_allocator()); - for (;;) { - Token token = tokenizer_get_token(&p->tokenizer); - if (token.kind == Token_Invalid) - return false; - gb_array_append(p->tokens, token); - - if (token.kind == Token_EOF) - break; - } - - p->cursor = &p->tokens[0]; - - // NOTE(bill): Is this big enough or too small? - isize arena_size = gb_max(gb_size_of(AstNode), gb_size_of(AstScope)); - arena_size *= 2*gb_array_count(p->tokens); - gb_arena_init_from_allocator(&p->arena, gb_heap_allocator(), arena_size); - - open_ast_scope(p); - p->file_scope = p->curr_scope; - - return true; - } - return false; -} - -void destroy_parser(Parser *p) { - close_ast_scope(p); - gb_arena_free(&p->arena); - gb_array_free(p->tokens); - destroy_tokenizer(&p->tokenizer); -} - -gb_internal void add_ast_entity(Parser *p, AstScope *scope, AstNode *declaration, AstNode *name_list) { +gb_internal void add_ast_entity(AstFile *f, AstScope *scope, AstNode *declaration, AstNode *name_list) { for (AstNode *n = name_list; n != NULL; n = n->next) { if (n->kind != AstNode_Identifier) { - print_parse_error(p, ast_node_token(declaration), "Identifier is already declared or resolved"); + ast_file_err(f, ast_node_token(declaration), "Identifier is already declared or resolved"); continue; } - AstEntity *entity = make_ast_entity(p, n->identifier.token, declaration, scope); + AstEntity *entity = make_ast_entity(f, n->identifier.token, declaration, scope); n->identifier.entity = entity; AstEntity *insert_entity = ast_scope_insert(scope, *entity); if (insert_entity != NULL && !are_strings_equal(insert_entity->token.string, make_string("_"))) { - print_parse_error(p, entity->token, - "There is already a previous declaration of `%.*s` in the current scope at (%td:%td)", - LIT(insert_entity->token.string), - insert_entity->token.line, insert_entity->token.column); + ast_file_err(f, entity->token, + "There is already a previous declaration of `%.*s` in the current scope at (%td:%td)", + LIT(insert_entity->token.string), + insert_entity->token.line, insert_entity->token.column); } } } -AstNode *parse_expression(Parser *p, b32 lhs); +AstNode *parse_expression(AstFile *f, b32 lhs); -AstNode *parse_identifier(Parser *p) { - Token token = p->cursor[0]; +AstNode *parse_identifier(AstFile *f) { + Token token = f->cursor[0]; if (token.kind == Token_Identifier) { - next_token(p); + next_token(f); } else { token.string = make_string("_"); - expect_token(p, Token_Identifier); + expect_token(f, Token_Identifier); } - return make_identifier(p, token); + return make_identifier(f, token); } -AstNode *parse_tag_expression(Parser *p, AstNode *expression) { - Token token = expect_token(p, Token_Hash); - Token name = expect_token(p, Token_Identifier); - return make_tag_expression(p, token, name, expression); +AstNode *parse_tag_expression(AstFile *f, AstNode *expression) { + Token token = expect_token(f, Token_Hash); + Token name = expect_token(f, Token_Identifier); + return make_tag_expression(f, token, name, expression); } -AstNode *parse_tag_statement(Parser *p, AstNode *statement) { - Token token = expect_token(p, Token_Hash); - Token name = expect_token(p, Token_Identifier); - return make_tag_statement(p, token, name, statement); +AstNode *parse_tag_statement(AstFile *f, AstNode *statement) { + Token token = expect_token(f, Token_Hash); + Token name = expect_token(f, Token_Identifier); + return make_tag_statement(f, token, name, statement); } AstNode *unparen_expression(AstNode *node) { @@ -828,11 +830,11 @@ AstNode *unparen_expression(AstNode *node) { } } -AstNode *parse_atom_expression(Parser *p, b32 lhs) { +AstNode *parse_atom_expression(AstFile *f, b32 lhs) { AstNode *operand = NULL; // Operand - switch (p->cursor[0].kind) { + switch (f->cursor[0].kind) { case Token_Identifier: - operand = parse_identifier(p); + operand = parse_identifier(f); if (!lhs) { // TODO(bill): Handle? } @@ -842,29 +844,29 @@ AstNode *parse_atom_expression(Parser *p, b32 lhs) { case Token_Float: case Token_String: case Token_Rune: - operand = make_basic_literal(p, p->cursor[0]); - next_token(p); + operand = make_basic_literal(f, f->cursor[0]); + next_token(f); break; case Token_OpenParen: { Token open, close; // NOTE(bill): Skip the Paren Expression - open = expect_token(p, Token_OpenParen); - operand = parse_expression(p, false); - close = expect_token(p, Token_CloseParen); - operand = make_paren_expression(p, operand, open, close); + open = expect_token(f, Token_OpenParen); + operand = parse_expression(f, false); + close = expect_token(f, Token_CloseParen); + operand = make_paren_expression(f, operand, open, close); } break; case Token_Hash: { - operand = parse_tag_expression(p, NULL); - operand->tag_expression.expression = parse_expression(p, false); + operand = parse_tag_expression(f, NULL); + operand->tag_expression.expression = parse_expression(f, false); } break; } b32 loop = true; while (loop) { - switch (p->cursor[0].kind) { + switch (f->cursor[0].kind) { case Token_OpenParen: { if (lhs) { // TODO(bill): Handle this shit! Is this even allowed in this language?! @@ -874,43 +876,43 @@ AstNode *parse_atom_expression(Parser *p, b32 lhs) { isize arg_list_count = 0; Token open_paren, close_paren; - open_paren = expect_token(p, Token_OpenParen); + open_paren = expect_token(f, Token_OpenParen); - while (p->cursor[0].kind != Token_CloseParen && - p->cursor[0].kind != Token_EOF) { - if (p->cursor[0].kind == Token_Comma) - print_parse_error(p, p->cursor[0], "Expected an expression not a ,"); + while (f->cursor[0].kind != Token_CloseParen && + f->cursor[0].kind != Token_EOF) { + if (f->cursor[0].kind == Token_Comma) + ast_file_err(f, f->cursor[0], "Expected an expression not a ,"); - DLIST_APPEND(arg_list, arg_list_curr, parse_expression(p, false)); + DLIST_APPEND(arg_list, arg_list_curr, parse_expression(f, false)); arg_list_count++; - if (p->cursor[0].kind != Token_Comma) { - if (p->cursor[0].kind == Token_CloseParen) + if (f->cursor[0].kind != Token_Comma) { + if (f->cursor[0].kind == Token_CloseParen) break; } - next_token(p); + next_token(f); } - close_paren = expect_token(p, Token_CloseParen); + close_paren = expect_token(f, Token_CloseParen); - operand = make_call_expression(p, operand, arg_list, arg_list_count, open_paren, close_paren); + operand = make_call_expression(f, operand, arg_list, arg_list_count, open_paren, close_paren); } break; case Token_Period: { - Token token = p->cursor[0]; - next_token(p); + Token token = f->cursor[0]; + next_token(f); if (lhs) { // TODO(bill): handle this } - switch (p->cursor[0].kind) { + switch (f->cursor[0].kind) { case Token_Identifier: - operand = make_selector_expression(p, token, operand, parse_identifier(p)); + operand = make_selector_expression(f, token, operand, parse_identifier(f)); break; default: { - print_parse_error(p, p->cursor[0], "Expected a selector"); - next_token(p); - operand = make_selector_expression(p, p->cursor[0], operand, NULL); + ast_file_err(f, f->cursor[0], "Expected a selector"); + next_token(f); + operand = make_selector_expression(f, f->cursor[0], operand, NULL); } break; } } break; @@ -922,44 +924,44 @@ AstNode *parse_atom_expression(Parser *p, b32 lhs) { Token open, close; AstNode *indices[3] = {}; - open = expect_token(p, Token_OpenBracket); - if (p->cursor[0].kind != Token_Colon) - indices[0] = parse_expression(p, false); + open = expect_token(f, Token_OpenBracket); + if (f->cursor[0].kind != Token_Colon) + indices[0] = parse_expression(f, false); isize colon_count = 0; Token colons[2] = {}; - while (p->cursor[0].kind == Token_Colon && colon_count < 2) { - colons[colon_count++] = p->cursor[0]; - next_token(p); - if (p->cursor[0].kind != Token_Colon && - p->cursor[0].kind != Token_CloseBracket && - p->cursor[0].kind != Token_EOF) { - indices[colon_count] = parse_expression(p, false); + while (f->cursor[0].kind == Token_Colon && colon_count < 2) { + colons[colon_count++] = f->cursor[0]; + next_token(f); + if (f->cursor[0].kind != Token_Colon && + f->cursor[0].kind != Token_CloseBracket && + f->cursor[0].kind != Token_EOF) { + indices[colon_count] = parse_expression(f, false); } } - close = expect_token(p, Token_CloseBracket); + close = expect_token(f, Token_CloseBracket); if (colon_count == 0) { - operand = make_index_expression(p, operand, indices[0], open, close); + operand = make_index_expression(f, operand, indices[0], open, close); } else { b32 triple_indexed = false; if (colon_count == 2) { triple_indexed = true; if (indices[1] == NULL) { - print_parse_error(p, colons[0], "Second index is required in a triple indexed slice"); - indices[1] = make_bad_expression(p, colons[0], colons[1]); + ast_file_err(f, colons[0], "Second index is required in a triple indexed slice"); + indices[1] = make_bad_expression(f, colons[0], colons[1]); } if (indices[2] == NULL) { - print_parse_error(p, colons[1], "Third index is required in a triple indexed slice"); - indices[2] = make_bad_expression(p, colons[1], close); + ast_file_err(f, colons[1], "Third index is required in a triple indexed slice"); + indices[2] = make_bad_expression(f, colons[1], close); } } - operand = make_slice_expression(p, operand, open, close, indices[0], indices[1], indices[2], triple_indexed); + operand = make_slice_expression(f, operand, open, close, indices[0], indices[1], indices[2], triple_indexed); } } break; case Token_Pointer: // Deference - operand = make_dereference_expression(p, operand, expect_token(p, Token_Pointer)); + operand = make_dereference_expression(f, operand, expect_token(f, Token_Pointer)); break; default: @@ -973,77 +975,77 @@ AstNode *parse_atom_expression(Parser *p, b32 lhs) { return operand; } -AstNode *parse_type(Parser *p); +AstNode *parse_type(AstFile *f); -AstNode *parse_unary_expression(Parser *p, b32 lhs) { - switch (p->cursor[0].kind) { +AstNode *parse_unary_expression(AstFile *f, b32 lhs) { + switch (f->cursor[0].kind) { case Token_Pointer: case Token_Add: case Token_Sub: case Token_Not: case Token_Xor: { AstNode *operand; - Token op = p->cursor[0]; - next_token(p); - operand = parse_unary_expression(p, false); - return make_unary_expression(p, op, operand); + Token op = f->cursor[0]; + next_token(f); + operand = parse_unary_expression(f, false); + return make_unary_expression(f, op, operand); } break; case Token_cast: { AstNode *type_expression, *operand; - Token token = p->cursor[0]; - next_token(p); - expect_token(p, Token_OpenParen); - type_expression = parse_type(p); - expect_token(p, Token_CloseParen); - operand = parse_unary_expression(p, false); - return make_cast_expression(p, token, type_expression, operand); + Token token = f->cursor[0]; + next_token(f); + expect_token(f, Token_OpenParen); + type_expression = parse_type(f); + expect_token(f, Token_CloseParen); + operand = parse_unary_expression(f, false); + return make_cast_expression(f, token, type_expression, operand); } break; } - return parse_atom_expression(p, lhs); + return parse_atom_expression(f, lhs); } -AstNode *parse_binary_expression(Parser *p, b32 lhs, i32 prec_in) { - AstNode *expression = parse_unary_expression(p, lhs); - for (i32 prec = token_precedence(p->cursor[0]); prec >= prec_in; prec--) { +AstNode *parse_binary_expression(AstFile *f, b32 lhs, i32 prec_in) { + AstNode *expression = parse_unary_expression(f, lhs); + for (i32 prec = token_precedence(f->cursor[0]); prec >= prec_in; prec--) { for (;;) { AstNode *right; - Token op = p->cursor[0]; + Token op = f->cursor[0]; i32 op_prec = token_precedence(op); if (op_prec != prec) break; - expect_operator(p); // NOTE(bill): error checks too + expect_operator(f); // NOTE(bill): error checks too if (lhs) { // TODO(bill): error checking lhs = false; } - right = parse_binary_expression(p, false, prec+1); + right = parse_binary_expression(f, false, prec+1); if (!right) - print_parse_error(p, op, "Expected expression on the right hand side of the binary operator"); - expression = make_binary_expression(p, op, expression, right); + ast_file_err(f, op, "Expected expression on the right hand side of the binary operator"); + expression = make_binary_expression(f, op, expression, right); } } return expression; } -AstNode *parse_expression(Parser *p, b32 lhs) { - return parse_binary_expression(p, lhs, 0+1); +AstNode *parse_expression(AstFile *f, b32 lhs) { + return parse_binary_expression(f, lhs, 0+1); } -AstNode *parse_expression_list(Parser *p, b32 lhs, isize *list_count_) { +AstNode *parse_expression_list(AstFile *f, b32 lhs, isize *list_count_) { AstNode *list_root = NULL; AstNode *list_curr = NULL; isize list_count = 0; do { - DLIST_APPEND(list_root, list_curr, parse_expression(p, lhs)); + DLIST_APPEND(list_root, list_curr, parse_expression(f, lhs)); list_count++; - if (p->cursor[0].kind != Token_Comma || - p->cursor[0].kind == Token_EOF) + if (f->cursor[0].kind != Token_Comma || + f->cursor[0].kind == Token_EOF) break; - next_token(p); + next_token(f); } while (true); if (list_count_) *list_count_ = list_count; @@ -1051,22 +1053,22 @@ AstNode *parse_expression_list(Parser *p, b32 lhs, isize *list_count_) { return list_root; } -AstNode *parse_lhs_expression_list(Parser *p, isize *list_count) { - return parse_expression_list(p, true, list_count); +AstNode *parse_lhs_expression_list(AstFile *f, isize *list_count) { + return parse_expression_list(f, true, list_count); } -AstNode *parse_rhs_expression_list(Parser *p, isize *list_count) { - return parse_expression_list(p, false, list_count); +AstNode *parse_rhs_expression_list(AstFile *f, isize *list_count) { + return parse_expression_list(f, false, list_count); } -AstNode *parse_declaration(Parser *p, AstNode *name_list, isize name_list_count); +AstNode *parse_declaration(AstFile *f, AstNode *name_list, isize name_list_count); -AstNode *parse_simple_statement(Parser *p) { +AstNode *parse_simple_statement(AstFile *f) { isize lhs_count = 0, rhs_count = 0; - AstNode *lhs_expression_list = parse_lhs_expression_list(p, &lhs_count); + AstNode *lhs_expression_list = parse_lhs_expression_list(f, &lhs_count); AstNode *statement = NULL; - Token token = p->cursor[0]; + Token token = f->cursor[0]; switch (token.kind) { case Token_Eq: case Token_AddEq: @@ -1081,86 +1083,86 @@ AstNode *parse_simple_statement(Parser *p) { case Token_CmpAndEq: case Token_CmpOrEq: { - if (p->curr_scope == p->file_scope) { - print_parse_error(p, p->cursor[0], "You cannot use a simple statement in the file scope"); - return make_bad_statement(p, p->cursor[0], p->cursor[0]); + if (f->curr_scope == f->file_scope) { + ast_file_err(f, f->cursor[0], "You cannot use a simple statement in the file scope"); + return make_bad_statement(f, f->cursor[0], f->cursor[0]); } - next_token(p); - AstNode *rhs_expression_list = parse_rhs_expression_list(p, &rhs_count); + next_token(f); + AstNode *rhs_expression_list = parse_rhs_expression_list(f, &rhs_count); if (rhs_expression_list == NULL) { - print_parse_error(p, token, "No right-hand side in assignment statement."); - return make_bad_statement(p, token, p->cursor[0]); + ast_file_err(f, token, "No right-hand side in assignment statement."); + return make_bad_statement(f, token, f->cursor[0]); } - return make_assign_statement(p, token, + return make_assign_statement(f, token, lhs_expression_list, lhs_count, rhs_expression_list, rhs_count); } break; case Token_Colon: // Declare - return parse_declaration(p, lhs_expression_list, lhs_count); + return parse_declaration(f, lhs_expression_list, lhs_count); } if (lhs_count > 1) { - print_parse_error(p, token, "Expected 1 expression"); - return make_bad_statement(p, token, p->cursor[0]); + ast_file_err(f, token, "Expected 1 expression"); + return make_bad_statement(f, token, f->cursor[0]); } - token = p->cursor[0]; + token = f->cursor[0]; switch (token.kind) { case Token_Increment: case Token_Decrement: - if (p->curr_scope == p->file_scope) { - print_parse_error(p, p->cursor[0], "You cannot use a simple statement in the file scope"); - return make_bad_statement(p, p->cursor[0], p->cursor[0]); + if (f->curr_scope == f->file_scope) { + ast_file_err(f, f->cursor[0], "You cannot use a simple statement in the file scope"); + return make_bad_statement(f, f->cursor[0], f->cursor[0]); } - statement = make_inc_dec_statement(p, token, lhs_expression_list); - next_token(p); + statement = make_inc_dec_statement(f, token, lhs_expression_list); + next_token(f); return statement; } - return make_expression_statement(p, lhs_expression_list); + return make_expression_statement(f, lhs_expression_list); } -AstNode *parse_statement_list(Parser *p, isize *list_count_); -AstNode *parse_statement(Parser *p); -AstNode *parse_body(Parser *p, AstScope *scope); +AstNode *parse_statement_list(AstFile *f, isize *list_count_); +AstNode *parse_statement(AstFile *f); +AstNode *parse_body(AstFile *f, AstScope *scope); -AstNode *parse_block_statement(Parser *p) { - if (p->curr_scope == p->file_scope) { - print_parse_error(p, p->cursor[0], "You cannot use a block statement in the file scope"); - return make_bad_statement(p, p->cursor[0], p->cursor[0]); +AstNode *parse_block_statement(AstFile *f) { + if (f->curr_scope == f->file_scope) { + ast_file_err(f, f->cursor[0], "You cannot use a block statement in the file scope"); + return make_bad_statement(f, f->cursor[0], f->cursor[0]); } AstNode *block_statement; - open_ast_scope(p); - block_statement = parse_body(p, p->curr_scope); - close_ast_scope(p); + open_ast_scope(f); + block_statement = parse_body(f, f->curr_scope); + close_ast_scope(f); return block_statement; } -AstNode *convert_statement_to_expression(Parser *p, AstNode *statement, char *kind) { +AstNode *convert_statement_to_expression(AstFile *f, AstNode *statement, char *kind) { if (statement == NULL) return NULL; if (statement->kind == AstNode_ExpressionStatement) return statement->expression_statement.expression; - print_parse_error(p, p->cursor[0], "Expected `%s`, found a simple statement.", kind); - return make_bad_expression(p, p->cursor[0], p->cursor[1]); + ast_file_err(f, f->cursor[0], "Expected `%s`, found a simple statement.", kind); + return make_bad_expression(f, f->cursor[0], f->cursor[1]); } -AstNode *parse_identfier_list(Parser *p, isize *list_count_) { +AstNode *parse_identfier_list(AstFile *f, isize *list_count_) { AstNode *list_root = NULL; AstNode *list_curr = NULL; isize list_count = 0; do { - DLIST_APPEND(list_root, list_curr, parse_identifier(p)); + DLIST_APPEND(list_root, list_curr, parse_identifier(f)); list_count++; - if (p->cursor[0].kind != Token_Comma || - p->cursor[0].kind == Token_EOF) + if (f->cursor[0].kind != Token_Comma || + f->cursor[0].kind == Token_EOF) break; - next_token(p); + next_token(f); } while (true); if (list_count_) *list_count_ = list_count; @@ -1169,116 +1171,116 @@ AstNode *parse_identfier_list(Parser *p, isize *list_count_) { } -AstNode *parse_identifier_or_type(Parser *p); +AstNode *parse_identifier_or_type(AstFile *f); -AstNode *parse_type_attempt(Parser *p) { - AstNode *type = parse_identifier_or_type(p); +AstNode *parse_type_attempt(AstFile *f) { + AstNode *type = parse_identifier_or_type(f); if (type != NULL) { // TODO(bill): Handle? } return type; } -AstNode *parse_type(Parser *p) { - AstNode *type = parse_type_attempt(p); +AstNode *parse_type(AstFile *f) { + AstNode *type = parse_type_attempt(f); if (type == NULL) { - Token token = p->cursor[0]; - print_parse_error(p, token, "Expected a type"); - next_token(p); - return make_bad_expression(p, token, p->cursor[0]); + Token token = f->cursor[0]; + ast_file_err(f, token, "Expected a type"); + next_token(f); + return make_bad_expression(f, token, f->cursor[0]); } return type; } -AstNode *parse_field_declaration(Parser *p, AstScope *scope) { +AstNode *parse_field_declaration(AstFile *f, AstScope *scope) { AstNode *name_list = NULL; isize name_list_count = 0; - name_list = parse_lhs_expression_list(p, &name_list_count); + name_list = parse_lhs_expression_list(f, &name_list_count); if (name_list_count == 0) - print_parse_error(p, p->cursor[0], "Empty field declaration"); + ast_file_err(f, f->cursor[0], "Empty field declaration"); - expect_token(p, Token_Colon); + expect_token(f, Token_Colon); - AstNode *type_expression = parse_type_attempt(p); + AstNode *type_expression = parse_type_attempt(f); if (type_expression == NULL) - print_parse_error(p, p->cursor[0], "Expected a type for this field declaration"); + ast_file_err(f, f->cursor[0], "Expected a type for this field declaration"); - AstNode *field = make_field(p, name_list, name_list_count, type_expression); - add_ast_entity(p, scope, field, name_list); + AstNode *field = make_field(f, name_list, name_list_count, type_expression); + add_ast_entity(f, scope, field, name_list); return field; } -Token parse_procedure_signature(Parser *p, AstScope *scope, +Token parse_procedure_signature(AstFile *f, AstScope *scope, AstNode **param_list, isize *param_count, AstNode **result_list, isize *result_count); -AstNode *parse_procedure_type(Parser *p, AstScope **scope_) { - AstScope *scope = make_ast_scope(p, p->file_scope); // Procedure's scope +AstNode *parse_procedure_type(AstFile *f, AstScope **scope_) { + AstScope *scope = make_ast_scope(f, f->file_scope); // Procedure's scope AstNode *params = NULL; AstNode *results = NULL; isize param_count = 0; isize result_count = 0; - Token proc_token = parse_procedure_signature(p, scope, ¶ms, ¶m_count, &results, &result_count); + Token proc_token = parse_procedure_signature(f, scope, ¶ms, ¶m_count, &results, &result_count); if (scope_) *scope_ = scope; - return make_procedure_type(p, proc_token, params, param_count, results, result_count); + return make_procedure_type(f, proc_token, params, param_count, results, result_count); } -AstNode *parse_identifier_or_type(Parser *p) { - switch (p->cursor[0].kind) { +AstNode *parse_identifier_or_type(AstFile *f) { + switch (f->cursor[0].kind) { case Token_Identifier: - return parse_identifier(p); + return parse_identifier(f); case Token_Pointer: - return make_pointer_type(p, expect_token(p, Token_Pointer), parse_type(p)); + return make_pointer_type(f, expect_token(f, Token_Pointer), parse_type(f)); case Token_OpenBracket: { - Token token = expect_token(p, Token_OpenBracket); + Token token = expect_token(f, Token_OpenBracket); AstNode *count_expression = NULL; - if (p->cursor[0].kind != Token_CloseBracket) - count_expression = parse_expression(p, false); - expect_token(p, Token_CloseBracket); - return make_array_type(p, token, count_expression, parse_type(p)); + if (f->cursor[0].kind != Token_CloseBracket) + count_expression = parse_expression(f, false); + expect_token(f, Token_CloseBracket); + return make_array_type(f, token, count_expression, parse_type(f)); } case Token_struct: { - Token token = expect_token(p, Token_struct); + Token token = expect_token(f, Token_struct); Token open, close; AstNode *field_list = NULL; AstNode *field_list_curr = NULL; isize field_list_count = 0; - open = expect_token(p, Token_OpenBrace); + open = expect_token(f, Token_OpenBrace); - AstScope *scope = make_ast_scope(p, NULL); // NOTE(bill): The struct needs its own scope with NO parent - while (p->cursor[0].kind == Token_Identifier || - p->cursor[0].kind == Token_Mul) { - DLIST_APPEND(field_list, field_list_curr, parse_field_declaration(p, scope)); - expect_token(p, Token_Semicolon); + AstScope *scope = make_ast_scope(f, NULL); // NOTE(bill): The struct needs its own scope with NO parent + while (f->cursor[0].kind == Token_Identifier || + f->cursor[0].kind == Token_Mul) { + DLIST_APPEND(field_list, field_list_curr, parse_field_declaration(f, scope)); + expect_token(f, Token_Semicolon); field_list_count++; } destroy_ast_scope(scope); - close = expect_token(p, Token_CloseBrace); + close = expect_token(f, Token_CloseBrace); - return make_struct_type(p, token, field_list, field_list_count); + return make_struct_type(f, token, field_list, field_list_count); } case Token_proc: - return parse_procedure_type(p, NULL); + return parse_procedure_type(f, NULL); case Token_OpenParen: { // NOTE(bill): Skip the paren expression AstNode *type_expression; Token open, close; - open = expect_token(p, Token_OpenParen); - type_expression = parse_type(p); - close = expect_token(p, Token_CloseParen); - return make_paren_expression(p, type_expression, open, close); + open = expect_token(f, Token_OpenParen); + type_expression = parse_type(f); + close = expect_token(f, Token_CloseParen); + return make_paren_expression(f, type_expression, open, close); } case Token_Colon: @@ -1286,55 +1288,55 @@ AstNode *parse_identifier_or_type(Parser *p) { break; default: - print_parse_error(p, p->cursor[0], - "Expected a type after `%.*s`, got `%.*s`", LIT(p->cursor[-1].string), LIT(p->cursor[0].string)); + ast_file_err(f, f->cursor[0], + "Expected a type after `%.*s`, got `%.*s`", LIT(f->cursor[-1].string), LIT(f->cursor[0].string)); break; } return NULL; } -AstNode *parse_parameters(Parser *p, AstScope *scope, isize *param_count_) { +AstNode *parse_parameters(AstFile *f, AstScope *scope, isize *param_count_) { AstNode *param_list = NULL; AstNode *param_list_curr = NULL; isize param_count = 0; - expect_token(p, Token_OpenParen); - while (p->cursor[0].kind != Token_CloseParen) { - AstNode *field = parse_field_declaration(p, scope); + expect_token(f, Token_OpenParen); + while (f->cursor[0].kind != Token_CloseParen) { + AstNode *field = parse_field_declaration(f, scope); DLIST_APPEND(param_list, param_list_curr, field); param_count += field->field.name_list_count; - if (p->cursor[0].kind != Token_Comma) + if (f->cursor[0].kind != Token_Comma) break; - next_token(p); + next_token(f); } - expect_token(p, Token_CloseParen); + expect_token(f, Token_CloseParen); if (param_count_) *param_count_ = param_count; return param_list; } -AstNode *parse_results(Parser *p, AstScope *scope, isize *result_count) { - if (allow_token(p, Token_ArrowRight)) { - if (p->cursor[0].kind == Token_OpenParen) { - expect_token(p, Token_OpenParen); +AstNode *parse_results(AstFile *f, AstScope *scope, isize *result_count) { + if (allow_token(f, Token_ArrowRight)) { + if (f->cursor[0].kind == Token_OpenParen) { + expect_token(f, Token_OpenParen); AstNode *list = NULL; AstNode *list_curr = NULL; isize count = 0; - while (p->cursor[0].kind != Token_CloseParen && - p->cursor[0].kind != Token_EOF) { - DLIST_APPEND(list, list_curr, parse_type(p)); + while (f->cursor[0].kind != Token_CloseParen && + f->cursor[0].kind != Token_EOF) { + DLIST_APPEND(list, list_curr, parse_type(f)); count++; - if (p->cursor[0].kind != Token_Comma) + if (f->cursor[0].kind != Token_Comma) break; - next_token(p); + next_token(f); } - expect_token(p, Token_CloseParen); + expect_token(f, Token_CloseParen); if (result_count) *result_count = count; return list; } - AstNode *result = parse_type(p); + AstNode *result = parse_type(f); if (result_count) *result_count = 1; return result; } @@ -1342,258 +1344,270 @@ AstNode *parse_results(Parser *p, AstScope *scope, isize *result_count) { return NULL; } -Token parse_procedure_signature(Parser *p, AstScope *scope, +Token parse_procedure_signature(AstFile *f, AstScope *scope, AstNode **param_list, isize *param_count, AstNode **result_list, isize *result_count) { - Token proc_token = expect_token(p, Token_proc); - *param_list = parse_parameters(p, scope, param_count); - *result_list = parse_results(p, scope, result_count); + Token proc_token = expect_token(f, Token_proc); + *param_list = parse_parameters(f, scope, param_count); + *result_list = parse_results(f, scope, result_count); return proc_token; } -AstNode *parse_body(Parser *p, AstScope *scope) { +AstNode *parse_body(AstFile *f, AstScope *scope) { AstNode *statement_list = NULL; isize statement_list_count = 0; Token open, close; - open = expect_token(p, Token_OpenBrace); - statement_list = parse_statement_list(p, &statement_list_count); - close = expect_token(p, Token_CloseBrace); + open = expect_token(f, Token_OpenBrace); + statement_list = parse_statement_list(f, &statement_list_count); + close = expect_token(f, Token_CloseBrace); - return make_block_statement(p, statement_list, statement_list_count, open, close); + return make_block_statement(f, statement_list, statement_list_count, open, close); } -AstNode *parse_procedure_declaration(Parser *p, Token proc_token, AstNode *name, DeclarationKind kind) { +AstNode *parse_procedure_declaration(AstFile *f, Token proc_token, AstNode *name, DeclarationKind kind) { AstNode *param_list = NULL; AstNode *result_list = NULL; isize param_count = 0; isize result_count = 0; - AstScope *scope = open_ast_scope(p); + AstScope *scope = open_ast_scope(f); - parse_procedure_signature(p, scope, ¶m_list, ¶m_count, &result_list, &result_count); + parse_procedure_signature(f, scope, ¶m_list, ¶m_count, &result_list, &result_count); AstNode *body = NULL; AstNode *tag_list = NULL; AstNode *tag_list_curr = NULL; isize tag_count = 0; - while (p->cursor[0].kind == Token_Hash) { - DLIST_APPEND(tag_list, tag_list_curr, parse_tag_expression(p, NULL)); + while (f->cursor[0].kind == Token_Hash) { + DLIST_APPEND(tag_list, tag_list_curr, parse_tag_expression(f, NULL)); tag_count++; } - if (p->cursor[0].kind == Token_OpenBrace) { - body = parse_body(p, scope); + if (f->cursor[0].kind == Token_OpenBrace) { + body = parse_body(f, scope); } - close_ast_scope(p); + close_ast_scope(f); - AstNode *proc_type = make_procedure_type(p, proc_token, param_list, param_count, result_list, result_count); - return make_procedure_declaration(p, kind, name, proc_type, body, tag_list, tag_count); + AstNode *proc_type = make_procedure_type(f, proc_token, param_list, param_count, result_list, result_count); + return make_procedure_declaration(f, kind, name, proc_type, body, tag_list, tag_count); } -AstNode *parse_declaration(Parser *p, AstNode *name_list, isize name_list_count) { +AstNode *parse_declaration(AstFile *f, AstNode *name_list, isize name_list_count) { AstNode *value_list = NULL; AstNode *type_expression = NULL; isize value_list_count = 0; - if (allow_token(p, Token_Colon)) { - type_expression = parse_identifier_or_type(p); - } else if (p->cursor[0].kind != Token_Eq && p->cursor[0].kind != Token_Semicolon) { - print_parse_error(p, p->cursor[0], "Expected type separator `:` or `=`"); + if (allow_token(f, Token_Colon)) { + type_expression = parse_identifier_or_type(f); + } else if (f->cursor[0].kind != Token_Eq && f->cursor[0].kind != Token_Semicolon) { + ast_file_err(f, f->cursor[0], "Expected type separator `:` or `=`"); } DeclarationKind declaration_kind = Declaration_Mutable; - if (p->cursor[0].kind == Token_Eq || - p->cursor[0].kind == Token_Colon) { - if (p->cursor[0].kind == Token_Colon) + if (f->cursor[0].kind == Token_Eq || + f->cursor[0].kind == Token_Colon) { + if (f->cursor[0].kind == Token_Colon) declaration_kind = Declaration_Immutable; - next_token(p); + next_token(f); - if (p->cursor[0].kind == Token_proc) { // NOTE(bill): Procedure declarations - Token proc_token = p->cursor[0]; + if (f->cursor[0].kind == Token_proc) { // NOTE(bill): Procedure declarations + Token proc_token = f->cursor[0]; AstNode *name = name_list; if (name_list_count != 1) { - print_parse_error(p, proc_token, "You can only declare one procedure at a time (at the moment)"); - return make_bad_declaration(p, name->identifier.token, proc_token); + ast_file_err(f, proc_token, "You can only declare one procedure at a time (at the moment)"); + return make_bad_declaration(f, name->identifier.token, proc_token); } // TODO(bill): Allow for mutable procedures if (declaration_kind != Declaration_Immutable) { - print_parse_error(p, proc_token, "Only immutable procedures are supported (at the moment)"); - return make_bad_declaration(p, name->identifier.token, proc_token); + ast_file_err(f, proc_token, "Only immutable procedures are supported (at the moment)"); + return make_bad_declaration(f, name->identifier.token, proc_token); } - AstNode *procedure_declaration = parse_procedure_declaration(p, proc_token, name, declaration_kind); - add_ast_entity(p, p->curr_scope, procedure_declaration, name_list); + AstNode *procedure_declaration = parse_procedure_declaration(f, proc_token, name, declaration_kind); + add_ast_entity(f, f->curr_scope, procedure_declaration, name_list); return procedure_declaration; } else { - value_list = parse_rhs_expression_list(p, &value_list_count); + value_list = parse_rhs_expression_list(f, &value_list_count); if (value_list_count > name_list_count) { - print_parse_error(p, p->cursor[0], "Too many values on the right hand side of the declaration"); + ast_file_err(f, f->cursor[0], "Too many values on the right hand side of the declaration"); } else if (value_list_count < name_list_count && declaration_kind == Declaration_Immutable) { - print_parse_error(p, p->cursor[0], "All constant declarations must be defined"); + ast_file_err(f, f->cursor[0], "All constant declarations must be defined"); } else if (value_list == NULL) { - print_parse_error(p, p->cursor[0], "Expected an expression for this declaration"); + ast_file_err(f, f->cursor[0], "Expected an expression for this declaration"); } } } if (declaration_kind == Declaration_Mutable) { if (type_expression == NULL && value_list == NULL) { - print_parse_error(p, p->cursor[0], "Missing variable type or initialization"); - return make_bad_declaration(p, p->cursor[0], p->cursor[0]); + ast_file_err(f, f->cursor[0], "Missing variable type or initialization"); + return make_bad_declaration(f, f->cursor[0], f->cursor[0]); } } else if (declaration_kind == Declaration_Immutable) { if (type_expression == NULL && value_list == NULL && name_list_count > 0) { - print_parse_error(p, p->cursor[0], "Missing constant value"); - return make_bad_declaration(p, p->cursor[0], p->cursor[0]); + ast_file_err(f, f->cursor[0], "Missing constant value"); + return make_bad_declaration(f, f->cursor[0], f->cursor[0]); } } else { - print_parse_error(p, p->cursor[0], "Unknown type of variable declaration"); - return make_bad_declaration(p, p->cursor[0], p->cursor[0]); + ast_file_err(f, f->cursor[0], "Unknown type of variable declaration"); + return make_bad_declaration(f, f->cursor[0], f->cursor[0]); } - AstNode *variable_declaration = make_variable_declaration(p, declaration_kind, name_list, name_list_count, type_expression, value_list, value_list_count); - add_ast_entity(p, p->curr_scope, variable_declaration, name_list); + AstNode *variable_declaration = make_variable_declaration(f, declaration_kind, name_list, name_list_count, type_expression, value_list, value_list_count); + add_ast_entity(f, f->curr_scope, variable_declaration, name_list); return variable_declaration; } -AstNode *parse_if_statement(Parser *p) { - if (p->curr_scope == p->file_scope) { - print_parse_error(p, p->cursor[0], "You cannot use an if statement in the file scope"); - return make_bad_statement(p, p->cursor[0], p->cursor[0]); +AstNode *parse_if_statement(AstFile *f) { + if (f->curr_scope == f->file_scope) { + ast_file_err(f, f->cursor[0], "You cannot use an if statement in the file scope"); + return make_bad_statement(f, f->cursor[0], f->cursor[0]); } - Token token = expect_token(p, Token_if); + Token token = expect_token(f, Token_if); AstNode *cond, *body, *else_statement; - open_ast_scope(p); + open_ast_scope(f); - cond = convert_statement_to_expression(p, parse_simple_statement(p), "boolean expression"); + cond = convert_statement_to_expression(f, parse_simple_statement(f), "boolean expression"); if (cond == NULL) { - print_parse_error(p, p->cursor[0], "Expected condition for if statement"); + ast_file_err(f, f->cursor[0], "Expected condition for if statement"); } - body = parse_block_statement(p); + body = parse_block_statement(f); else_statement = NULL; - if (allow_token(p, Token_else)) { - switch (p->cursor[0].kind) { + if (allow_token(f, Token_else)) { + switch (f->cursor[0].kind) { case Token_if: - else_statement = parse_if_statement(p); + else_statement = parse_if_statement(f); break; case Token_OpenBrace: - else_statement = parse_block_statement(p); + else_statement = parse_block_statement(f); break; default: - print_parse_error(p, p->cursor[0], "Expected if statement block statement"); - else_statement = make_bad_statement(p, p->cursor[0], p->cursor[1]); + ast_file_err(f, f->cursor[0], "Expected if statement block statement"); + else_statement = make_bad_statement(f, f->cursor[0], f->cursor[1]); break; } } - close_ast_scope(p); - return make_if_statement(p, token, cond, body, else_statement); + close_ast_scope(f); + return make_if_statement(f, token, cond, body, else_statement); } -AstNode *parse_return_statement(Parser *p) { - if (p->curr_scope == p->file_scope) { - print_parse_error(p, p->cursor[0], "You cannot use a return statement in the file scope"); - return make_bad_statement(p, p->cursor[0], p->cursor[0]); +AstNode *parse_return_statement(AstFile *f) { + if (f->curr_scope == f->file_scope) { + ast_file_err(f, f->cursor[0], "You cannot use a return statement in the file scope"); + return make_bad_statement(f, f->cursor[0], f->cursor[0]); } - Token token = expect_token(p, Token_return); + Token token = expect_token(f, Token_return); AstNode *result = NULL; isize result_count = 0; - if (p->cursor[0].kind != Token_Semicolon) - result = parse_rhs_expression_list(p, &result_count); - expect_token(p, Token_Semicolon); + if (f->cursor[0].kind != Token_Semicolon) + result = parse_rhs_expression_list(f, &result_count); + expect_token(f, Token_Semicolon); - return make_return_statement(p, token, result, result_count); + return make_return_statement(f, token, result, result_count); } -AstNode *parse_for_statement(Parser *p) { - if (p->curr_scope == p->file_scope) { - print_parse_error(p, p->cursor[0], "You cannot use a for statement in the file scope"); - return make_bad_statement(p, p->cursor[0], p->cursor[0]); +AstNode *parse_for_statement(AstFile *f) { + if (f->curr_scope == f->file_scope) { + ast_file_err(f, f->cursor[0], "You cannot use a for statement in the file scope"); + return make_bad_statement(f, f->cursor[0], f->cursor[0]); } - Token token = expect_token(p, Token_for); - open_ast_scope(p); + Token token = expect_token(f, Token_for); + open_ast_scope(f); AstNode *init_statement = NULL, *cond = NULL, *end_statement = NULL, *body = NULL; - if (p->cursor[0].kind != Token_OpenBrace) { - cond = parse_simple_statement(p); + if (f->cursor[0].kind != Token_OpenBrace) { + cond = parse_simple_statement(f); if (is_ast_node_complex_statement(cond)) { - print_parse_error(p, p->cursor[0], - "You are not allowed that type of statement in a for statement, it's too complex!"); + ast_file_err(f, f->cursor[0], + "You are not allowed that type of statement in a for statement, it's too complex!"); } - if (allow_token(p, Token_Semicolon)) { + if (allow_token(f, Token_Semicolon)) { init_statement = cond; cond = NULL; - if (p->cursor[0].kind != Token_Semicolon) { - cond = parse_simple_statement(p); + if (f->cursor[0].kind != Token_Semicolon) { + cond = parse_simple_statement(f); } - expect_token(p, Token_Semicolon); - if (p->cursor[0].kind != Token_OpenBrace) { - end_statement = parse_simple_statement(p); + expect_token(f, Token_Semicolon); + if (f->cursor[0].kind != Token_OpenBrace) { + end_statement = parse_simple_statement(f); } } } - body = parse_block_statement(p); + body = parse_block_statement(f); - close_ast_scope(p); + close_ast_scope(f); - return make_for_statement(p, token, init_statement, cond, end_statement, body); + return make_for_statement(f, token, init_statement, cond, end_statement, body); } -AstNode *parse_defer_statement(Parser *p) { - if (p->curr_scope == p->file_scope) { - print_parse_error(p, p->cursor[0], "You cannot use a defer statement in the file scope"); - return make_bad_statement(p, p->cursor[0], p->cursor[0]); +AstNode *parse_defer_statement(AstFile *f) { + if (f->curr_scope == f->file_scope) { + ast_file_err(f, f->cursor[0], "You cannot use a defer statement in the file scope"); + return make_bad_statement(f, f->cursor[0], f->cursor[0]); } - Token token = expect_token(p, Token_defer); - AstNode *statement = parse_statement(p); + Token token = expect_token(f, Token_defer); + AstNode *statement = parse_statement(f); switch (statement->kind) { case AstNode_EmptyStatement: - print_parse_error(p, token, "Empty statement after defer (e.g. `;`)"); + ast_file_err(f, token, "Empty statement after defer (e.g. `;`)"); break; case AstNode_DeferStatement: - print_parse_error(p, token, "You cannot defer a defer statement"); + ast_file_err(f, token, "You cannot defer a defer statement"); break; case AstNode_ReturnStatement: - print_parse_error(p, token, "You cannot a return statement"); + ast_file_err(f, token, "You cannot a return statement"); break; } - return make_defer_statement(p, token, statement); + return make_defer_statement(f, token, statement); } -AstNode *parse_type_declaration(Parser *p) { - Token token = expect_token(p, Token_type); - AstNode *name = parse_identifier(p); - expect_token(p, Token_Colon); - AstNode *type_expression = parse_type(p); +AstNode *parse_type_declaration(AstFile *f) { + Token token = expect_token(f, Token_type); + AstNode *name = parse_identifier(f); + expect_token(f, Token_Colon); + AstNode *type_expression = parse_type(f); - AstNode *type_declaration = make_type_declaration(p, token, name, type_expression); + AstNode *type_declaration = make_type_declaration(f, token, name, type_expression); if (type_expression->kind != AstNode_StructType && type_expression->kind != AstNode_ProcedureType) - expect_token(p, Token_Semicolon); + expect_token(f, Token_Semicolon); return type_declaration; } -AstNode *parse_statement(Parser *p) { +AstNode *parse_import_declaration(AstFile *f) { + Token token = expect_token(f, Token_import); + Token filepath = expect_token(f, Token_String); + if (f->curr_scope == f->file_scope) { + return make_import_declaration(f, token, filepath); + } + ast_file_err(f, token, "You cannot `import` within a procedure. This must be done at the file scope."); + return make_bad_declaration(f, token, filepath); +} + +AstNode *parse_statement(AstFile *f) { AstNode *s = NULL; - Token token = p->cursor[0]; + Token token = f->cursor[0]; switch (token.kind) { case Token_type: - return parse_type_declaration(p); + return parse_type_declaration(f); + case Token_import: + return parse_import_declaration(f); // Operands case Token_Identifier: @@ -1607,46 +1621,46 @@ AstNode *parse_statement(Parser *p) { case Token_Sub: case Token_Xor: case Token_Not: - s = parse_simple_statement(p); - if (s->kind != AstNode_ProcedureDeclaration && !allow_token(p, Token_Semicolon)) { - print_parse_error(p, p->cursor[0], "Expected `;` after statement, got `%s`", token_kind_to_string(p->cursor[0].kind)); + s = parse_simple_statement(f); + if (s->kind != AstNode_ProcedureDeclaration && !allow_token(f, Token_Semicolon)) { + ast_file_err(f, f->cursor[0], "Expected `;` after statement, got `%s`", token_kind_to_string(f->cursor[0].kind)); } return s; // TODO(bill): other keywords - case Token_if: return parse_if_statement(p); - case Token_return: return parse_return_statement(p); - case Token_for: return parse_for_statement(p); - case Token_defer: return parse_defer_statement(p); + case Token_if: return parse_if_statement(f); + case Token_return: return parse_return_statement(f); + case Token_for: return parse_for_statement(f); + case Token_defer: return parse_defer_statement(f); // case Token_match: // case Token_case: case Token_Hash: - s = parse_tag_statement(p, NULL); - s->tag_statement.statement = parse_statement(p); // TODO(bill): Find out why this doesn't work as an argument + s = parse_tag_statement(f, NULL); + s->tag_statement.statement = parse_statement(f); // TODO(bill): Find out why this doesn't work as an argument return s; - case Token_OpenBrace: return parse_block_statement(p); + case Token_OpenBrace: return parse_block_statement(f); case Token_Semicolon: - s = make_empty_statement(p, token); - next_token(p); + s = make_empty_statement(f, token); + next_token(f); return s; } - print_parse_error(p, token, "Expected a statement, got `%s`", token_kind_to_string(token.kind)); - return make_bad_statement(p, token, p->cursor[0]); + ast_file_err(f, token, "Expected a statement, got `%s`", token_kind_to_string(token.kind)); + return make_bad_statement(f, token, f->cursor[0]); } -AstNode *parse_statement_list(Parser *p, isize *list_count_) { +AstNode *parse_statement_list(AstFile *f, isize *list_count_) { AstNode *list_root = NULL; AstNode *list_curr = NULL; isize list_count = 0; - while (p->cursor[0].kind != Token_case && - p->cursor[0].kind != Token_CloseBrace && - p->cursor[0].kind != Token_EOF) { - DLIST_APPEND(list_root, list_curr, parse_statement(p)); + while (f->cursor[0].kind != Token_case && + f->cursor[0].kind != Token_CloseBrace && + f->cursor[0].kind != Token_EOF) { + DLIST_APPEND(list_root, list_curr, parse_statement(f)); list_count++; } @@ -1654,3 +1668,148 @@ AstNode *parse_statement_list(Parser *p, isize *list_count_) { return list_root; } + + +// void parse_file(AstFile *f, ) + + +b32 init_ast_file(AstFile *f, String fullpath) { + if (init_tokenizer(&f->tokenizer, fullpath)) { + gb_array_init(f->tokens, gb_heap_allocator()); + for (;;) { + Token token = tokenizer_get_token(&f->tokenizer); + if (token.kind == Token_Invalid) + return false; + gb_array_append(f->tokens, token); + + if (token.kind == Token_EOF) + break; + } + + f->cursor = &f->tokens[0]; + + // NOTE(bill): Is this big enough or too small? + isize arena_size = gb_max(gb_size_of(AstNode), gb_size_of(AstScope)); + arena_size *= 2*gb_array_count(f->tokens); + gb_arena_init_from_allocator(&f->arena, gb_heap_allocator(), arena_size); + + open_ast_scope(f); + f->file_scope = f->curr_scope; + + return true; + } + return false; +} + +void destroy_ast_file(AstFile *f) { + close_ast_scope(f); + gb_arena_free(&f->arena); + gb_array_free(f->tokens); + gb_free(gb_heap_allocator(), f->tokenizer.fullpath.text); + destroy_tokenizer(&f->tokenizer); +} + +b32 init_parser(Parser *p) { + gb_array_init(p->files, gb_heap_allocator()); + gb_array_init(p->imports, gb_heap_allocator()); + return true; +} + +void destroy_parser(Parser *p) { +#if 0 + // TODO(bill): Fix memory leak + for (isize i = 0; i < gb_array_count(p->files); i++) { + destroy_ast_file(&p->files[i]); + } + for (isize i = 0; i < gb_array_count(p->imports); i++) { + // gb_free(gb_heap_allocator(), p->imports[i].text); + } + gb_array_free(p->files); + gb_array_free(p->imports); +#endif +} + +// NOTE(bill): Returns true if it's added +b32 try_add_import_path(Parser *p, String import_file) { + for (isize i = 0; i < gb_array_count(p->imports); i++) { + String import = p->imports[i]; + if (are_strings_equal(import, import_file)) { + return false; + } + } + + gb_array_append(p->imports, import_file); + return true; +} + + +void parse_file(Parser *p, AstFile *f) { + f->declarations = parse_statement_list(f, &f->declaration_count); + + String filepath = f->tokenizer.fullpath; + String base_dir = filepath; + for (isize i = filepath.len-1; i >= 0; i--) { + if (base_dir.text[i] == GB_PATH_SEPARATOR) + break; + base_dir.len--; + } + + for (AstNode *node = f->declarations; node != NULL; node = node->next) { + if (!is_ast_node_declaration(node)) { + // NOTE(bill): Sanity check + ast_file_err(f, ast_node_token(node), "Only declarations are allowed at file scope"); + } else { + if (node->kind == AstNode_ImportDeclaration) { + auto *id = &node->import_declaration; + String file = id->filepath.string; + String file_str = {}; + if (file.text[0] == '"') + file_str = make_string(file.text+1, file.len-2); + + char ext[] = ".odin"; + isize ext_len = gb_size_of(ext)-1; + if (file_str.len > ext_len) { + if (gb_memcompare(file_str.text+file_str.len-ext_len, ext, ext_len) == 0) { + file_str.len -= ext_len; + } + } + + isize str_len = base_dir.len + file_str.len + ext_len; + u8 *str = gb_alloc_array(gb_heap_allocator(), u8, str_len+1); + defer (gb_free(gb_heap_allocator(), str)); + + gb_memcopy(str, base_dir.text, base_dir.len); + gb_memcopy(str+base_dir.len, file_str.text, file_str.len); + gb_memcopy(str+base_dir.len+file_str.len, ext, ext_len+1); + str[str_len] = '\0'; + char *path_str = gb_path_get_full_name(gb_heap_allocator(), cast(char *)str); + String import_file = make_string(path_str); + + if (!try_add_import_path(p, import_file)) { + gb_free(gb_heap_allocator(), import_file.text); + } + } + } + } +} + + +void parse_files(Parser *p, char *init_filename) { + char *fullpath_str = gb_path_get_full_name(gb_heap_allocator(), init_filename); + String init_fullpath = make_string(fullpath_str); + gb_array_append(p->imports, init_fullpath); + + for (isize i = 0; i < gb_array_count(p->imports); i++) { + String import_path = p->imports[i]; + AstFile file = {}; + b32 ok = init_ast_file(&file, import_path); + if (!ok) { + gb_printf_err("Failed to parse file: %.*s", LIT(import_path)); + return; + } + parse_file(p, &file); + gb_array_append(p->files, file); + } +} + + |