From c5ef5279d4346fe1b38815060303b17159adbc82 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Thu, 15 Jun 2017 14:42:08 +0100 Subject: Add foreign variables --- src/parser.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 12 deletions(-) (limited to 'src/parser.cpp') diff --git a/src/parser.cpp b/src/parser.cpp index c22e0e19c..4f0595d78 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1704,6 +1704,24 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) { case AstNode_ProcDecl: return s->ProcDecl.body != NULL; + case AstNode_GenDecl: + if (s->GenDecl.close.pos.line != 0) { + return true; + } + if (s->GenDecl.specs.count == 1) { + return is_semicolon_optional_for_node(f, s->GenDecl.specs[0]); + } + break; + + case AstNode_ForeignBlockDecl: + if (s->ForeignBlockDecl.close.pos.line != 0) { + return true; + } + if (s->ForeignBlockDecl.decls.count == 1) { + return is_semicolon_optional_for_node(f, s->ForeignBlockDecl.decls[0]); + } + break; + case AstNode_TypeSpec: return is_semicolon_optional_for_node(f, s->TypeSpec.type); } @@ -1716,6 +1734,9 @@ void expect_semicolon(AstFile *f, AstNode *s) { return; } Token prev_token = f->prev_token; + if (prev_token.kind == Token_Semicolon) { + return; + } switch (f->curr_token.kind) { case Token_EOF: @@ -1736,8 +1757,32 @@ void expect_semicolon(AstFile *f, AstNode *s) { // break; // } } + String node_string = ast_node_strings[s->kind]; + if (s->kind == AstNode_GenDecl) { + switch (s->GenDecl.token.kind) { + case Token_var: + case Token_let: + node_string = str_lit("variable declaration"); + break; + case Token_const: + node_string = str_lit("const declaration"); + break; + case Token_type: + node_string = str_lit("type declaration"); + break; + case Token_import: + case Token_import_load: + node_string = str_lit("import declaration"); + break; + case Token_foreign_library: + case Token_foreign_system_library: + node_string = str_lit("foreign library declaration"); + break; + } + } + syntax_error(prev_token, "Expected `;` after %.*s, got %.*s", - LIT(ast_node_strings[s->kind]), LIT(token_strings[prev_token.kind])); + LIT(node_string), LIT(token_strings[prev_token.kind])); } else { syntax_error(prev_token, "Expected `;`"); } @@ -2572,7 +2617,8 @@ AstNode *parse_gen_decl(AstFile *f, Token token, ParseSpecFunc *func) { } } else { array_init(&specs, heap_allocator(), 1); - array_add(&specs, func(f, token)); + AstNode *spec = func(f, token); + array_add(&specs, spec); } if (specs.count == 0) { @@ -2764,25 +2810,29 @@ PARSE_SPEC_FUNC(parse_foreign_library_spec) { AstNode *parse_decl(AstFile *f); void parse_foreign_block_decl(AstFile *f, Array *decls) { - AstNode *decl = parse_decl(f); + AstNode *decl = parse_stmt(f); switch (decl->kind) { + case AstNode_EmptyStmt: + case AstNode_BadStmt: case AstNode_BadDecl: - break; + return; case AstNode_ProcDecl: array_add(decls, decl); - break; + return; - // case AstNode_GenDecl: - // if (decl->GenDecl.token.kind == Token_var) { - // array_add(decls, decl); - // break; - // } + case AstNode_GenDecl: + switch (decl->GenDecl.token.kind) { + case Token_var: + case Token_let: + array_add(decls, decl); + return; + } /* fallthrough */ default: error_node(decl, "Only procedures declarations are allowed within a foreign block at the moment"); - break; + return; } } @@ -3944,7 +3994,9 @@ AstNode *parse_stmt(AstFile *f) { case Token_foreign: case Token_foreign_library: case Token_foreign_system_library: - return parse_decl(f); + s = parse_decl(f); + expect_semicolon(f, s); + return s; case Token_if: return parse_if_stmt(f); -- cgit v1.2.3