diff options
Diffstat (limited to 'src/parser.cpp')
| -rw-r--r-- | src/parser.cpp | 262 |
1 files changed, 142 insertions, 120 deletions
diff --git a/src/parser.cpp b/src/parser.cpp index 94f8fd42c..942e83f29 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3016,9 +3016,10 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { syntax_error(token, "Expected a type or range, got nothing"); } - if (allow_token(f, Token_Semicolon)) { + if (f->curr_token.kind == Token_Semicolon && f->curr_token.string == ";") { + expect_token(f, Token_Semicolon); underlying = parse_type(f); - } else if (allow_token(f, Token_Comma)) { + } else if (allow_token(f, Token_Comma) || allow_token(f, Token_Semicolon)) { String p = token_to_string(f->prev_token); syntax_error(token_end_of_line(f, f->prev_token), "Expected a semicolon, got a %.*s", LIT(p)); @@ -3273,6 +3274,8 @@ gb_internal Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) { case Token_OpenBracket: { bool prev_allow_range = f->allow_range; f->allow_range = false; + defer (f->allow_range = prev_allow_range); + Token open = {}, close = {}, interval = {}; Ast *indices[2] = {}; @@ -3281,6 +3284,13 @@ gb_internal Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) { f->expr_level++; open = expect_token(f, Token_OpenBracket); + if (f->curr_token.kind == Token_CloseBracket) { + error(f->curr_token, "Expected an operand, got ]"); + close = expect_token(f, Token_CloseBracket); + operand = ast_index_expr(f, operand, nullptr, open, close); + break; + } + switch (f->curr_token.kind) { case Token_Ellipsis: case Token_RangeFull: @@ -3330,7 +3340,6 @@ gb_internal Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) { operand = ast_index_expr(f, operand, indices[0], open, close); } - f->allow_range = prev_allow_range; } break; case Token_Pointer: // Deference @@ -4342,30 +4351,132 @@ gb_internal Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_fl } - if (f->curr_token.kind == Token_Colon) { - Array<Ast *> names = convert_to_ident_list(f, list, true, allow_poly_names); // Copy for semantic reasons + if (f->curr_token.kind != Token_Colon) { + // NOTE(bill): proc(Type, Type, Type) + for (AstAndFlags const &item : list) { + Ast *type = item.node; + Token token = blank_token; + if (allowed_flags&FieldFlag_Results) { + // NOTE(bill): Make this nothing and not `_` + token.string = str_lit(""); + } + + auto names = array_make<Ast *>(ast_allocator(f), 1); + token.pos = ast_token(type).pos; + names[0] = ast_ident(f, token); + u32 flags = check_field_prefixes(f, list.count, allowed_flags, item.flags); + Token tag = {}; + Ast *param = ast_field(f, names, item.node, nullptr, flags, tag, docs, f->line_comment); + array_add(¶ms, param); + } + + if (name_count_) *name_count_ = total_name_count; + return ast_field_list(f, start_token, params); + } + + // NOTE(bill): proc(ident, ident, ident: Type) + + if (f->prev_token.kind == Token_Comma) { + syntax_error(f->prev_token, "Trailing comma before a colon is not allowed"); + } + Array<Ast *> names = convert_to_ident_list(f, list, true, allow_poly_names); // Copy for semantic reasons + if (names.count == 0) { + syntax_error(f->curr_token, "Empty field declaration"); + } + bool any_polymorphic_names = check_procedure_name_list(names); + u32 set_flags = 0; + if (list.count > 0) { + set_flags = list[0].flags; + } + set_flags = check_field_prefixes(f, names.count, allowed_flags, set_flags); + total_name_count += names.count; + + Ast *type = nullptr; + Ast *default_value = nullptr; + Token tag = {}; + + expect_token_after(f, Token_Colon, "field list"); + if (f->curr_token.kind != Token_Eq) { + type = parse_var_type(f, allow_ellipsis, allow_typeid_token); + Ast *tt = unparen_expr(type); + if (tt == nullptr) { + syntax_error(f->prev_token, "Invalid type expression in field list"); + } else if (is_signature && !any_polymorphic_names && tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) { + syntax_error(type, "Specialization of typeid is not allowed without polymorphic names"); + } + } + + if (allow_token(f, Token_Eq)) { + default_value = parse_expr(f, false); + if (!allow_default_parameters) { + syntax_error(f->curr_token, "Default parameters are only allowed for procedures"); + default_value = nullptr; + } + } + + if (default_value != nullptr && names.count > 1) { + syntax_error(f->curr_token, "Default parameters can only be applied to single values"); + } + + if (allowed_flags == FieldFlag_Struct && default_value != nullptr) { + syntax_error(default_value, "Default parameters are not allowed for structs"); + default_value = nullptr; + } + + if (type != nullptr && type->kind == Ast_Ellipsis) { + if (seen_ellipsis) syntax_error(type, "Extra variadic parameter after ellipsis"); + seen_ellipsis = true; + if (names.count != 1) { + syntax_error(type, "Variadic parameters can only have one field name"); + } + } else if (seen_ellipsis && default_value == nullptr) { + syntax_error(f->curr_token, "Extra parameter after ellipsis without a default value"); + } + + if (type != nullptr && default_value == nullptr) { + if (f->curr_token.kind == Token_String) { + tag = expect_token(f, Token_String); + if ((allowed_flags & FieldFlag_Tags) == 0) { + syntax_error(tag, "Field tags are only allowed within structures"); + } + } + } + + bool more_fields = allow_field_separator(f); + Ast *param = ast_field(f, names, type, default_value, set_flags, tag, docs, f->line_comment); + array_add(¶ms, param); + + if (!more_fields) { + if (name_count_) *name_count_ = total_name_count; + return ast_field_list(f, start_token, params); + } + + while (f->curr_token.kind != follow && + f->curr_token.kind != Token_EOF && + f->curr_token.kind != Token_Semicolon) { + CommentGroup *docs = f->lead_comment; + + if (!is_signature) parse_enforce_tabs(f); + u32 set_flags = parse_field_prefixes(f); + Token tag = {}; + Array<Ast *> names = parse_ident_list(f, allow_poly_names); if (names.count == 0) { syntax_error(f->curr_token, "Empty field declaration"); + break; } bool any_polymorphic_names = check_procedure_name_list(names); - u32 set_flags = 0; - if (list.count > 0) { - set_flags = list[0].flags; - } set_flags = check_field_prefixes(f, names.count, allowed_flags, set_flags); total_name_count += names.count; Ast *type = nullptr; Ast *default_value = nullptr; - Token tag = {}; - expect_token_after(f, Token_Colon, "field list"); if (f->curr_token.kind != Token_Eq) { type = parse_var_type(f, allow_ellipsis, allow_typeid_token); Ast *tt = unparen_expr(type); - if (tt == nullptr) { - syntax_error(f->prev_token, "Invalid type expression in field list"); - } else if (is_signature && !any_polymorphic_names && tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) { + if (is_signature && !any_polymorphic_names && + tt != nullptr && + tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) { syntax_error(type, "Specialization of typeid is not allowed without polymorphic names"); } } @@ -4382,11 +4493,6 @@ gb_internal Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_fl syntax_error(f->curr_token, "Default parameters can only be applied to single values"); } - if (allowed_flags == FieldFlag_Struct && default_value != nullptr) { - syntax_error(default_value, "Default parameters are not allowed for structs"); - default_value = nullptr; - } - if (type != nullptr && type->kind == Ast_Ellipsis) { if (seen_ellipsis) syntax_error(type, "Extra variadic parameter after ellipsis"); seen_ellipsis = true; @@ -4406,105 +4512,14 @@ gb_internal Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_fl } } - bool more_fields = allow_field_separator(f); + + bool ok = allow_field_separator(f); Ast *param = ast_field(f, names, type, default_value, set_flags, tag, docs, f->line_comment); array_add(¶ms, param); - if (!more_fields) { - if (name_count_) *name_count_ = total_name_count; - return ast_field_list(f, start_token, params); - } - - while (f->curr_token.kind != follow && - f->curr_token.kind != Token_EOF && - f->curr_token.kind != Token_Semicolon) { - CommentGroup *docs = f->lead_comment; - - if (!is_signature) parse_enforce_tabs(f); - u32 set_flags = parse_field_prefixes(f); - Token tag = {}; - Array<Ast *> names = parse_ident_list(f, allow_poly_names); - if (names.count == 0) { - syntax_error(f->curr_token, "Empty field declaration"); - break; - } - bool any_polymorphic_names = check_procedure_name_list(names); - set_flags = check_field_prefixes(f, names.count, allowed_flags, set_flags); - total_name_count += names.count; - - Ast *type = nullptr; - Ast *default_value = nullptr; - expect_token_after(f, Token_Colon, "field list"); - if (f->curr_token.kind != Token_Eq) { - type = parse_var_type(f, allow_ellipsis, allow_typeid_token); - Ast *tt = unparen_expr(type); - if (is_signature && !any_polymorphic_names && - tt != nullptr && - tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) { - syntax_error(type, "Specialization of typeid is not allowed without polymorphic names"); - } - } - - if (allow_token(f, Token_Eq)) { - default_value = parse_expr(f, false); - if (!allow_default_parameters) { - syntax_error(f->curr_token, "Default parameters are only allowed for procedures"); - default_value = nullptr; - } - } - - if (default_value != nullptr && names.count > 1) { - syntax_error(f->curr_token, "Default parameters can only be applied to single values"); - } - - if (type != nullptr && type->kind == Ast_Ellipsis) { - if (seen_ellipsis) syntax_error(type, "Extra variadic parameter after ellipsis"); - seen_ellipsis = true; - if (names.count != 1) { - syntax_error(type, "Variadic parameters can only have one field name"); - } - } else if (seen_ellipsis && default_value == nullptr) { - syntax_error(f->curr_token, "Extra parameter after ellipsis without a default value"); - } - - if (type != nullptr && default_value == nullptr) { - if (f->curr_token.kind == Token_String) { - tag = expect_token(f, Token_String); - if ((allowed_flags & FieldFlag_Tags) == 0) { - syntax_error(tag, "Field tags are only allowed within structures"); - } - } - } - - - bool ok = allow_field_separator(f); - Ast *param = ast_field(f, names, type, default_value, set_flags, tag, docs, f->line_comment); - array_add(¶ms, param); - - if (!ok) { - break; - } - } - - if (name_count_) *name_count_ = total_name_count; - return ast_field_list(f, start_token, params); - } - - for (AstAndFlags const &item : list) { - Ast *type = item.node; - Token token = blank_token; - if (allowed_flags&FieldFlag_Results) { - // NOTE(bill): Make this nothing and not `_` - token.string = str_lit(""); + if (!ok) { + break; } - - auto names = array_make<Ast *>(ast_allocator(f), 1); - token.pos = ast_token(type).pos; - names[0] = ast_ident(f, token); - u32 flags = check_field_prefixes(f, list.count, allowed_flags, item.flags); - Token tag = {}; - Ast *param = ast_field(f, names, item.node, nullptr, flags, tag, docs, f->line_comment); - array_add(¶ms, param); } if (name_count_) *name_count_ = total_name_count; @@ -4572,6 +4587,9 @@ gb_internal Ast *parse_do_body(AstFile *f, Token const &token, char const *msg) gb_internal bool parse_control_statement_semicolon_separator(AstFile *f) { Token tok = peek_token(f); if (tok.kind != Token_OpenBrace) { + if (f->curr_token.kind == Token_Semicolon && f->curr_token.string != ";") { + syntax_error(token_end_of_line(f, f->prev_token), "Expected ';', got newline"); + } return allow_token(f, Token_Semicolon); } if (f->curr_token.string == ";") { @@ -5776,7 +5794,7 @@ gb_internal AstPackage *try_add_import_path(Parser *p, String path, String const for (FileInfo fi : list) { String name = fi.name; String ext = path_extension(name); - if (ext == FILE_EXT) { + if (ext == FILE_EXT && !path_is_directory(name)) { files_with_ext += 1; } if (ext == FILE_EXT && !is_excluded_target_filename(name)) { @@ -5801,7 +5819,7 @@ gb_internal AstPackage *try_add_import_path(Parser *p, String path, String const for (FileInfo fi : list) { String name = fi.name; String ext = path_extension(name); - if (ext == FILE_EXT) { + if (ext == FILE_EXT && !path_is_directory(name)) { if (is_excluded_target_filename(name)) { continue; } @@ -6147,7 +6165,7 @@ gb_internal String build_tag_get_token(String s, String *out) { isize width = utf8_decode(&s[n], s.len-n, &rune); if (n == 0 && rune == '!') { - } else if (!rune_is_letter(rune) && !rune_is_digit(rune)) { + } else if (!rune_is_letter(rune) && !rune_is_digit(rune) && rune != ':') { isize k = gb_max(gb_max(n, width), 1); *out = substring(s, k, s.len); return substring(s, 0, k); @@ -6199,7 +6217,9 @@ gb_internal bool parse_build_tag(Token token_for_pos, String s) { continue; } - TargetOsKind os = get_target_os_from_string(p); + Subtarget subtarget = Subtarget_Default; + + TargetOsKind os = get_target_os_from_string(p, &subtarget); TargetArchKind arch = get_target_arch_from_string(p); num_tokens += 1; @@ -6213,11 +6233,13 @@ gb_internal bool parse_build_tag(Token token_for_pos, String s) { if (os != TargetOs_Invalid) { this_kind_os_seen = true; + bool same_subtarget = (subtarget == Subtarget_Default) || (subtarget == selected_subtarget); + GB_ASSERT(arch == TargetArch_Invalid); if (is_notted) { - this_kind_correct = this_kind_correct && (os != build_context.metrics.os); + this_kind_correct = this_kind_correct && (os != build_context.metrics.os || !same_subtarget); } else { - this_kind_correct = this_kind_correct && (os == build_context.metrics.os); + this_kind_correct = this_kind_correct && (os == build_context.metrics.os && same_subtarget); } } else if (arch != TargetArch_Invalid) { this_kind_arch_seen = true; |