diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-08-30 00:04:14 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-08-30 00:04:14 +0100 |
| commit | 0eaf7bd830dcda6e00f80eefed36bdf7beb02d5d (patch) | |
| tree | 3e65c52384458031b5ede490429c9c1938d8ba0b /src/parser.cpp | |
| parent | 593563d8eabf725ac851f4c3c72cd32b5a71aa7c (diff) | |
Begin "Everything's a namespace"
Diffstat (limited to 'src/parser.cpp')
| -rw-r--r-- | src/parser.cpp | 179 |
1 files changed, 151 insertions, 28 deletions
diff --git a/src/parser.cpp b/src/parser.cpp index a79cae37e..e3be11940 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -169,6 +169,7 @@ AST_NODE_KIND(_ComplexStmtBegin, struct{}) \ }) \ AST_NODE_KIND(DeferStmt, struct { Token token; AstNode *stmt; }) \ AST_NODE_KIND(BranchStmt, struct { Token token; }) \ + AST_NODE_KIND(UsingStmt, struct { Token token; AstNode *node; }) \ \ AST_NODE_KIND(_ComplexStmtEnd, struct{}) \ AST_NODE_KIND(_StmtEnd, struct{}) \ @@ -177,6 +178,7 @@ AST_NODE_KIND(_DeclBegin, struct{}) \ AST_NODE_KIND(VarDecl, struct { \ DeclKind kind; \ u32 tags; \ + b32 is_using; \ AstNode *name_list; \ AstNode *type; \ AstNode *value_list; \ @@ -222,8 +224,8 @@ AST_NODE_KIND(_TypeBegin, struct{}) \ }) \ AST_NODE_KIND(StructType, struct { \ Token token; \ - AstNode *field_list; \ - isize field_count; \ + AstNode *decl_list; \ + isize decl_count; \ b32 is_packed; \ }) \ AST_NODE_KIND(UnionType, struct { \ @@ -354,6 +356,8 @@ Token ast_node_token(AstNode *node) { return node->DeferStmt.token; case AstNode_BranchStmt: return node->BranchStmt.token; + case AstNode_UsingStmt: + return node->UsingStmt.token; case AstNode_BadDecl: return node->BadDecl.begin; case AstNode_VarDecl: @@ -707,6 +711,13 @@ gb_inline AstNode *make_branch_stmt(AstFile *f, Token token) { return result; } +gb_inline AstNode *make_using_stmt(AstFile *f, Token token, AstNode *node) { + AstNode *result = make_node(f, AstNode_UsingStmt); + result->UsingStmt.token = token; + result->UsingStmt.node = node; + return result; +} + gb_inline AstNode *make_bad_decl(AstFile *f, Token begin, Token end) { AstNode *result = make_node(f, AstNode_BadDecl); @@ -778,11 +789,11 @@ gb_inline AstNode *make_vector_type(AstFile *f, Token token, AstNode *count, Ast return result; } -gb_inline AstNode *make_struct_type(AstFile *f, Token token, AstNode *field_list, isize field_count, b32 is_packed) { +gb_inline AstNode *make_struct_type(AstFile *f, Token token, AstNode *decl_list, isize decl_count, b32 is_packed) { AstNode *result = make_node(f, AstNode_StructType); result->StructType.token = token; - result->StructType.field_list = field_list; - result->StructType.field_count = field_count; + result->StructType.decl_list = decl_list; + result->StructType.decl_count = decl_count; result->StructType.is_packed = is_packed; return result; } @@ -938,6 +949,32 @@ void fix_advance_to_next_stmt(AstFile *f) { #endif } +b32 expect_semicolon_after_stmt(AstFile *f, AstNode *s) { + if (s != NULL) { + switch (s->kind) { + case AstNode_ProcDecl: + return true; + case AstNode_TypeDecl: { + switch (s->TypeDecl.type->kind) { + case AstNode_StructType: + case AstNode_UnionType: + case AstNode_EnumType: + case AstNode_ProcType: + return true; + } + } break; + } + } + + if (!allow_token(f, Token_Semicolon)) { + // CLEANUP(bill): Semicolon handling in parser + ast_file_err(f, f->cursor[0], + "Expected `;` after %.*s, got `%.*s`", + LIT(ast_node_strings[s->kind]), LIT(token_strings[f->cursor[0].kind])); + return false; + } + return true; +} AstNode *parse_expr(AstFile *f, b32 lhs); @@ -1211,6 +1248,7 @@ b32 is_literal_type(AstNode *node) { switch (node->kind) { case AstNode_BadExpr: case AstNode_Ident: + case AstNode_SelectorExpr: case AstNode_ArrayType: case AstNode_VectorType: case AstNode_StructType: @@ -1652,10 +1690,19 @@ AstNode *parse_parameter_list(AstFile *f, AstScope *scope, isize *param_count_, return param_list; } + AstNode *parse_identifier_or_type(AstFile *f) { switch (f->cursor[0].kind) { - case Token_Identifier: - return parse_identifier(f); + case Token_Identifier: { + AstNode *ident = parse_identifier(f); + while (f->cursor[0].kind == Token_Period) { + Token token = f->cursor[0]; + next_token(f); + AstNode *sel = parse_identifier(f); + ident = make_selector_expr(f, token, ident, sel); + } + return ident; + } case Token_Pointer: return make_pointer_type(f, expect_token(f, Token_Pointer), parse_type(f)); @@ -1687,10 +1734,6 @@ AstNode *parse_identifier_or_type(AstFile *f) { case Token_struct: { Token token = expect_token(f, Token_struct); - Token open, close; - AstNode *params = NULL; - isize param_count = 0; - AstScope *scope = make_ast_scope(f, NULL); // NOTE(bill): The struct needs its own scope with NO parent b32 is_packed = false; if (allow_token(f, Token_Hash)) { Token tag = expect_token(f, Token_Identifier); @@ -1701,12 +1744,72 @@ AstNode *parse_identifier_or_type(AstFile *f) { } } - open = expect_token(f, Token_OpenBrace); - params = parse_parameter_list(f, scope, ¶m_count, Token_Semicolon, true); - close = expect_token(f, Token_CloseBrace); + AstScope *scope = make_ast_scope(f, NULL); // NOTE(bill): The struct needs its own scope with NO parent + AstScope *curr_scope = f->curr_scope; + f->curr_scope = scope; + defer (f->curr_scope = curr_scope); - return make_struct_type(f, token, params, param_count, is_packed); - } + + Token open = expect_token(f, Token_OpenBrace); + AstNode *decls = NULL; + AstNode *decls_curr = NULL; + isize decl_count = 0; + + while (f->cursor[0].kind == Token_Identifier || + f->cursor[0].kind == Token_using) { + b32 is_using = false; + if (allow_token(f, Token_using)) { + is_using = true; + } + isize name_count = 0; + AstNode *name_list = parse_lhs_expr_list(f, &name_count); + if (name_count == 0) { + ast_file_err(f, f->cursor[0], "Empty field declaration"); + } + + if (name_count > 1 && is_using) { + ast_file_err(f, f->cursor[0], "Cannot apply `using` to more than one of the same type"); + } + + AstNode *decl = NULL; + + if (f->cursor[0].kind == Token_Colon) { + decl = parse_decl(f, name_list, name_count); + + if (decl->kind == AstNode_ProcDecl) { + ast_file_err(f, f->cursor[0], "Procedure declarations are not allowed within a structure"); + decl = make_bad_decl(f, ast_node_token(name_list), f->cursor[0]); + } + } else { + ast_file_err(f, f->cursor[0], "Illegal structure field"); + decl = make_bad_decl(f, ast_node_token(name_list), f->cursor[0]); + } + + expect_semicolon_after_stmt(f, decl); + + if (decl != NULL && is_ast_node_decl(decl)) { + DLIST_APPEND(decls, decls_curr, decl); + if (decl->kind == AstNode_VarDecl) { + decl_count += decl->VarDecl.name_count; + decl->VarDecl.is_using = is_using; + + if (decl->VarDecl.kind == Declaration_Mutable) { + if (decl->VarDecl.value_count > 0) { + ast_file_err(f, f->cursor[0], "Default variable assignments within a structure will be ignored (at the moment)"); + } + } + + } else { + decl_count += 1; + } + } + } + Token close = expect_token(f, Token_CloseBrace); + + // params = parse_parameter_list(f, scope, ¶m_count, Token_Semicolon, true); + + return make_struct_type(f, token, decls, decl_count, is_packed); + } break; case Token_union: { Token token = expect_token(f, Token_union); @@ -2100,6 +2203,7 @@ AstNode *parse_defer_stmt(AstFile *f) { return make_defer_stmt(f, token, statement); } + AstNode *parse_stmt(AstFile *f) { AstNode *s = NULL; Token token = f->cursor[0]; @@ -2117,18 +2221,7 @@ AstNode *parse_stmt(AstFile *f) { case Token_Xor: case Token_Not: s = parse_simple_stmt(f); - if (s->kind != AstNode_ProcDecl && - (s->kind == AstNode_TypeDecl && - s->TypeDecl.type->kind != AstNode_StructType && - s->TypeDecl.type->kind != AstNode_UnionType && - s->TypeDecl.type->kind != AstNode_EnumType && - s->TypeDecl.type->kind != AstNode_ProcType) && - !allow_token(f, Token_Semicolon)) { - // CLEANUP(bill): Semicolon handling in parser - ast_file_err(f, f->cursor[0], - "Expected `;` after statement, got `%.*s`", - LIT(token_strings[f->cursor[0].kind])); - } + expect_semicolon_after_stmt(f, s); return s; // TODO(bill): other keywords @@ -2146,6 +2239,36 @@ AstNode *parse_stmt(AstFile *f) { expect_token(f, Token_Semicolon); return make_branch_stmt(f, token); + case Token_using: { + AstNode *node = NULL; + + next_token(f); + node = parse_stmt(f); + + b32 valid = false; + + switch (node->kind) { + case AstNode_ExprStmt: + if (node->ExprStmt.expr->kind == AstNode_Ident) { + valid = true; + } + break; + case AstNode_VarDecl: + if (node->VarDecl.kind == Declaration_Mutable) { + valid = true; + } + break; + } + + if (!valid) { + ast_file_err(f, token, "Illegal use of `using` statement."); + return make_bad_stmt(f, token, f->cursor[0]); + } + + + return make_using_stmt(f, token, node); + } break; + case Token_Hash: { s = parse_tag_stmt(f, NULL); |