aboutsummaryrefslogtreecommitdiff
path: root/src/parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.cpp')
-rw-r--r--src/parser.cpp1181
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, &params, &param_count, &results, &result_count);
+ Token proc_token = parse_procedure_signature(f, scope, &params, &param_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, &param_list, &param_count, &result_list, &result_count);
+ parse_procedure_signature(f, scope, &param_list, &param_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);
+ }
+}
+
+