diff options
Diffstat (limited to 'src/parser.cpp')
| -rw-r--r-- | src/parser.cpp | 465 |
1 files changed, 354 insertions, 111 deletions
diff --git a/src/parser.cpp b/src/parser.cpp index 6836e901f..a2d8ab1f9 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -35,6 +35,7 @@ struct AstFile { isize expr_level; bool allow_range; // NOTE(bill): Ranges are only allowed in certain cases bool in_foreign_block; + bool allow_type; Array<AstNode *> decls; bool is_global_scope; @@ -712,6 +713,10 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) { n->TypeAssertion.expr = clone_ast_node(a, n->TypeAssertion.expr); n->TypeAssertion.type = clone_ast_node(a, n->TypeAssertion.type); break; + case AstNode_TypeCast: + n->TypeCast.type = clone_ast_node(a, n->TypeCast.type); + n->TypeCast.expr = clone_ast_node(a, n->TypeCast.expr); + break; case AstNode_BadStmt: break; case AstNode_EmptyStmt: break; @@ -1623,39 +1628,39 @@ CommentGroup consume_comment_group(AstFile *f, isize n, isize *end_line_) { return comments; } +void comsume_comment_groups(AstFile *f, Token prev) { + if (f->curr_token.kind != Token_Comment) return; + CommentGroup comment = {}; + isize end_line = 0; -bool next_token(AstFile *f) { - gb_zero_item(&f->lead_comment); - gb_zero_item(&f->line_comment); - Token prev = f->prev_token = f->curr_token; - - bool ok = next_token0(f); - if (!ok) { - return false; - } - if (f->curr_token.kind == Token_Comment) { - CommentGroup comment = {}; - isize end_line = 0; - - if (f->curr_token.pos.line == prev.pos.line) { - comment = consume_comment_group(f, 0, &end_line); - if (f->curr_token.pos.line != end_line) { - f->line_comment = comment; - } + if (f->curr_token.pos.line == prev.pos.line) { + comment = consume_comment_group(f, 0, &end_line); + if (f->curr_token.pos.line != end_line) { + f->line_comment = comment; } + } - end_line = -1; - while (f->curr_token.kind == Token_Comment) { - comment = consume_comment_group(f, 1, &end_line); - } + end_line = -1; + while (f->curr_token.kind == Token_Comment) { + comment = consume_comment_group(f, 1, &end_line); + } - if (end_line+1 == f->curr_token.pos.line) { - f->lead_comment = comment; - } + if (end_line+1 == f->curr_token.pos.line) { + f->lead_comment = comment; } + GB_ASSERT(f->curr_token.kind != Token_Comment); +} - return true; + +Token advance_token(AstFile *f) { + gb_zero_item(&f->lead_comment); + gb_zero_item(&f->line_comment); + Token prev = f->prev_token = f->curr_token; + + bool ok = next_token0(f); + if (ok) comsume_comment_groups(f, prev); + return prev; } TokenKind look_ahead_token_kind(AstFile *f, isize amount) { @@ -1685,7 +1690,7 @@ Token expect_token(AstFile *f, TokenKind kind) { } } - next_token(f); + advance_token(f); return prev; } @@ -1698,7 +1703,7 @@ Token expect_token_after(AstFile *f, TokenKind kind, char *msg) { msg, LIT(p)); } - next_token(f); + advance_token(f); return prev; } @@ -1712,7 +1717,7 @@ Token expect_operator(AstFile *f) { syntax_error(f->curr_token, "Expected an non-range operator, got `%.*s`", LIT(token_strings[prev.kind])); } - next_token(f); + advance_token(f); return prev; } @@ -1722,14 +1727,14 @@ Token expect_keyword(AstFile *f) { syntax_error(f->curr_token, "Expected a keyword, got `%.*s`", LIT(token_strings[prev.kind])); } - next_token(f); + advance_token(f); return prev; } bool allow_token(AstFile *f, TokenKind kind) { Token prev = f->curr_token; if (prev.kind == kind) { - next_token(f); + advance_token(f); return true; } return false; @@ -1742,6 +1747,20 @@ bool is_blank_ident(String str) { } return false; } +bool is_blank_ident(Token token) { + if (token.kind == Token_Ident) { + return is_blank_ident(token.string); + } + return false; +} +bool is_blank_ident(AstNode *node) { + if (node->kind == AstNode_Ident) { + ast_node(i, Ident, node); + return is_blank_ident(i->token.string); + } + return false; +} + // NOTE(bill): Go to next statement to prevent numerous error messages popping up @@ -1791,7 +1810,7 @@ void fix_advance_to_next_stmt(AstFile *f) { // NOTE(bill): Reaching here means there is a parsing bug } break; } - next_token(f); + advance_token(f); } #endif } @@ -1801,7 +1820,7 @@ Token expect_closing(AstFile *f, TokenKind kind, String context) { f->curr_token.kind == Token_Semicolon && f->curr_token.string == "\n") { error(f->curr_token, "Missing `,` before newline in %.*s", LIT(context)); - next_token(f); + advance_token(f); } return expect_token(f, kind); } @@ -1923,7 +1942,7 @@ AstNode * parse_body(AstFile *f); AstNode *parse_ident(AstFile *f) { Token token = f->curr_token; if (token.kind == Token_Ident) { - next_token(f); + advance_token(f); } else { token.string = str_lit("_"); expect_token(f, Token_Ident); @@ -2079,7 +2098,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven syntax_error(tag_expr, "Invalid alternative link procedure name `%.*s`", LIT(*link_name)); } - next_token(f); + advance_token(f); } else { expect_token(f, Token_String); } @@ -2157,11 +2176,12 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven } -Array<AstNode *> parse_lhs_expr_list(AstFile *f); -Array<AstNode *> parse_rhs_expr_list(AstFile *f); -AstNode * parse_simple_stmt (AstFile *f, StmtAllowFlag flags); -AstNode * parse_type (AstFile *f); -AstNode * parse_call_expr (AstFile *f, AstNode *operand); +Array<AstNode *> parse_lhs_expr_list (AstFile *f); +Array<AstNode *> parse_rhs_expr_list (AstFile *f); +AstNode * parse_simple_stmt (AstFile *f, StmtAllowFlag flags); +AstNode * parse_type (AstFile *f); +AstNode * parse_call_expr (AstFile *f, AstNode *operand); +AstNode * parse_record_field_list(AstFile *f, isize *name_count_); AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) { if (statement == nullptr) { @@ -2195,6 +2215,7 @@ AstNode *convert_stmt_to_body(AstFile *f, AstNode *stmt) { + AstNode *parse_operand(AstFile *f, bool lhs) { AstNode *operand = nullptr; // Operand switch (f->curr_token.kind) { @@ -2211,21 +2232,16 @@ AstNode *parse_operand(AstFile *f, bool lhs) { case Token_Float: case Token_Imag: case Token_Rune: - operand = ast_basic_lit(f, f->curr_token); - next_token(f); - return operand; + return ast_basic_lit(f, advance_token(f)); case Token_size_of: case Token_align_of: - case Token_offset_of: { - operand = ast_implicit(f, f->curr_token); next_token(f); - return parse_call_expr(f, operand); - } + case Token_offset_of: + return parse_call_expr(f, ast_implicit(f, advance_token(f))); case Token_String: { - Token token = f->curr_token; - next_token(f); + Token token = advance_token(f); if (f->curr_token.kind == Token_String) { // NOTE(bill): Allow neighbouring string literals to be merge together to // become one big string @@ -2240,7 +2256,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) { isize old_count = data.count; array_resize(&data, data.count + s.len); gb_memmove(data.data+old_count, s.text, s.len); - next_token(f); + advance_token(f); } token.string = make_string(data.data, data.count); @@ -2332,7 +2348,242 @@ AstNode *parse_operand(AstFile *f, bool lhs) { return type; } + + // Check for Types + case Token_Dollar: { + Token token = expect_token(f, Token_Dollar); + AstNode *type = parse_ident(f); + return ast_poly_type(f, token, type); + } break; + + case Token_type_of: { + AstNode *i = ast_implicit(f, expect_token(f, Token_type_of)); + AstNode *type = parse_call_expr(f, i); + while (f->curr_token.kind == Token_Period) { + Token token = advance_token(f); + AstNode *sel = parse_ident(f); + type = ast_selector_expr(f, token, type, sel); + } + return type; + } break; + + case Token_Pointer: { + Token token = expect_token(f, Token_Pointer); + AstNode *elem = parse_type(f); + return ast_pointer_type(f, token, elem); + } break; + + case Token_atomic: { + Token token = expect_token(f, Token_atomic); + AstNode *elem = parse_type(f); + return ast_atomic_type(f, token, elem); + } break; + + case Token_OpenBracket: { + Token token = expect_token(f, Token_OpenBracket); + AstNode *count_expr = nullptr; + bool is_vector = false; + + if (f->curr_token.kind == Token_Ellipsis) { + count_expr = ast_unary_expr(f, expect_token(f, Token_Ellipsis), nullptr); + } else if (allow_token(f, Token_vector)) { + if (f->curr_token.kind != Token_CloseBracket) { + f->expr_level++; + count_expr = parse_expr(f, false); + f->expr_level--; + } else { + syntax_error(f->curr_token, "Vector type missing count"); + } + is_vector = true; + } else if (allow_token(f, Token_dynamic)) { + expect_token(f, Token_CloseBracket); + return ast_dynamic_array_type(f, token, parse_type(f)); + } else if (f->curr_token.kind != Token_CloseBracket) { + f->expr_level++; + count_expr = parse_expr(f, false); + f->expr_level--; + } + expect_token(f, Token_CloseBracket); + if (is_vector) { + return ast_vector_type(f, token, count_expr, parse_type(f)); + } + return ast_array_type(f, token, count_expr, parse_type(f)); + } break; + + case Token_map: { + Token token = expect_token(f, Token_map); + AstNode *count = nullptr; + AstNode *key = nullptr; + AstNode *value = nullptr; + + Token open = expect_token_after(f, Token_OpenBracket, "map"); + key = parse_expr(f, true); + if (allow_token(f, Token_Comma)) { + count = key; + key = parse_type(f); + } + Token close = expect_token(f, Token_CloseBracket); + value = parse_type(f); + + return ast_map_type(f, token, count, key, value); + } break; + + case Token_struct: { + Token token = expect_token(f, Token_struct); + bool is_packed = false; + bool is_ordered = false; + AstNode *align = nullptr; + + isize prev_level = f->expr_level; + f->expr_level = -1; + + while (allow_token(f, Token_Hash)) { + Token tag = expect_token_after(f, Token_Ident, "#"); + if (tag.string == "packed") { + if (is_packed) { + syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string)); + } + is_packed = true; + } else if (tag.string == "ordered") { + if (is_ordered) { + syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string)); + } + is_ordered = true; + } else if (tag.string == "align") { + if (align) { + syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string)); + } + align = parse_expr(f, true); + } else { + syntax_error(tag, "Invalid struct tag `#%.*s`", LIT(tag.string)); + } + } + + f->expr_level = prev_level; + + if (is_packed && is_ordered) { + syntax_error(token, "`#ordered` is not needed with `#packed` which implies ordering"); + } + + Token open = expect_token_after(f, Token_OpenBrace, "struct"); + + isize name_count = 0; + AstNode *fields = parse_record_field_list(f, &name_count); + Token close = expect_token(f, Token_CloseBrace); + + Array<AstNode *> decls = {}; + if (fields != nullptr) { + GB_ASSERT(fields->kind == AstNode_FieldList); + decls = fields->FieldList.list; + } + + return ast_struct_type(f, token, decls, name_count, is_packed, is_ordered, align); + } break; + + case Token_union: { + Token token = expect_token(f, Token_union); + Token open = expect_token_after(f, Token_OpenBrace, "union"); + Array<AstNode *> variants = make_ast_node_array(f); + isize total_decl_name_count = 0; + + CommentGroup docs = f->lead_comment; + Token start_token = f->curr_token; + + + while (f->curr_token.kind != Token_CloseBrace && + f->curr_token.kind != Token_EOF) { + AstNode *type = parse_type(f); + if (type->kind != AstNode_BadExpr) { + array_add(&variants, type); + } + if (!allow_token(f, Token_Comma)) { + break; + } + } + + Token close = expect_token(f, Token_CloseBrace); + + return ast_union_type(f, token, variants); + } break; + + case Token_raw_union: { + Token token = expect_token(f, Token_raw_union); + Token open = expect_token_after(f, Token_OpenBrace, "raw_union"); + + isize decl_count = 0; + AstNode *fields = parse_record_field_list(f, &decl_count); + Token close = expect_token(f, Token_CloseBrace); + + Array<AstNode *> decls = {}; + if (fields != nullptr) { + GB_ASSERT(fields->kind == AstNode_FieldList); + decls = fields->FieldList.list; + } + + return ast_raw_union_type(f, token, decls, decl_count); + } break; + + case Token_enum: { + Token token = expect_token(f, Token_enum); + AstNode *base_type = nullptr; + if (f->curr_token.kind != Token_OpenBrace) { + base_type = parse_type(f); + } + Token open = expect_token(f, Token_OpenBrace); + + Array<AstNode *> values = parse_element_list(f); + Token close = expect_token(f, Token_CloseBrace); + + return ast_enum_type(f, token, base_type, values); + } break; + + case Token_bit_field: { + Token token = expect_token(f, Token_bit_field); + Array<AstNode *> fields = make_ast_node_array(f); + AstNode *align = nullptr; + Token open, close; + + isize prev_level = f->expr_level; + f->expr_level = -1; + + while (allow_token(f, Token_Hash)) { + Token tag = expect_token_after(f, Token_Ident, "#"); + if (tag.string == "align") { + if (align) { + syntax_error(tag, "Duplicate bit_field tag `#%.*s`", LIT(tag.string)); + } + align = parse_expr(f, true); + } else { + syntax_error(tag, "Invalid bit_field tag `#%.*s`", LIT(tag.string)); + } + } + + f->expr_level = prev_level; + + open = expect_token_after(f, Token_OpenBrace, "bit_field"); + + while (f->curr_token.kind != Token_EOF && + f->curr_token.kind != Token_CloseBrace) { + AstNode *name = parse_ident(f); + Token colon = expect_token(f, Token_Colon); + AstNode *value = parse_expr(f, true); + + AstNode *field = ast_field_value(f, name, value, colon); + array_add(&fields, field); + + if (f->curr_token.kind != Token_Comma) { + break; + } + advance_token(f); + } + + close = expect_token(f, Token_CloseBrace); + + return ast_bit_field_type(f, token, fields, align); + } break; + default: { + #if 0 AstNode *type = parse_type_or_ident(f); if (type != nullptr) { // TODO(bill): Is this correct??? @@ -2341,6 +2592,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) { GB_ASSERT_MSG(type->kind != AstNode_Ident, "Type cannot be identifier %.*s(%td:%td)", LIT(pos.file), pos.line, pos.column); return type; } + #endif break; } } @@ -2385,7 +2637,7 @@ AstNode *parse_call_expr(AstFile *f, AstNode *operand) { if (f->curr_token.kind == Token_Ellipsis) { prefix_ellipsis = true; ellipsis = f->curr_token; - next_token(f); + advance_token(f); } AstNode *arg = parse_expr(f, false); @@ -2397,7 +2649,7 @@ AstNode *parse_call_expr(AstFile *f, AstNode *operand) { } if (f->curr_token.kind == Token_Ellipsis) { ellipsis = f->curr_token; - next_token(f); + advance_token(f); } AstNode *value = parse_value(f); @@ -2450,6 +2702,7 @@ AstNode *parse_macro_call_expr(AstFile *f, AstNode *operand) { AstNode *parse_atom_expr(AstFile *f, AstNode *operand, bool lhs) { if (operand == nullptr) { + if (f->allow_type) return nullptr; Token begin = f->curr_token; syntax_error(begin, "Expected an operand"); fix_advance_to_next_stmt(f); @@ -2467,8 +2720,7 @@ AstNode *parse_atom_expr(AstFile *f, AstNode *operand, bool lhs) { break; case Token_Period: { - Token token = f->curr_token; - next_token(f); + Token token = advance_token(f); switch (f->curr_token.kind) { case Token_Ident: operand = ast_selector_expr(f, token, operand, parse_ident(f)); @@ -2485,7 +2737,7 @@ AstNode *parse_atom_expr(AstFile *f, AstNode *operand, bool lhs) { default: syntax_error(f->curr_token, "Expected a selector"); - next_token(f); + advance_token(f); operand = ast_bad_expr(f, ast_node_token(operand), f->curr_token); // operand = ast_selector_expr(f, f->curr_token, operand, nullptr); break; @@ -2516,8 +2768,7 @@ AstNode *parse_atom_expr(AstFile *f, AstNode *operand, bool lhs) { while ((f->curr_token.kind == Token_Ellipsis || f->curr_token.kind == Token_HalfClosed) && ellipsis_count < gb_count_of(ellipses)) { - ellipses[ellipsis_count++] = f->curr_token; - next_token(f); + ellipses[ellipsis_count++] = advance_token(f); if (f->curr_token.kind != Token_Ellipsis && f->curr_token.kind != Token_HalfClosed && f->curr_token.kind != Token_CloseBracket && @@ -2583,8 +2834,7 @@ AstNode *parse_unary_expr(AstFile *f, bool lhs) { case Token_Not: case Token_Xor: case Token_And: { - Token op = f->curr_token; - next_token(f); + Token op = advance_token(f); return ast_unary_expr(f, op, parse_unary_expr(f, lhs)); } break; case Token_cast: { @@ -2703,7 +2953,7 @@ Array<AstNode *> parse_expr_list(AstFile *f, bool lhs) { f->curr_token.kind == Token_EOF) { break; } - next_token(f); + advance_token(f); } return list; @@ -2726,7 +2976,7 @@ Array<AstNode *> parse_ident_list(AstFile *f) { f->curr_token.kind == Token_EOF) { break; } - next_token(f); + advance_token(f); } while (true); return list; @@ -2744,9 +2994,8 @@ AstNode *parse_type_attempt(AstFile *f) { AstNode *parse_type(AstFile *f) { AstNode *type = parse_type_attempt(f); if (type == nullptr) { - Token token = f->curr_token; + Token token = advance_token(f); syntax_error(token, "Expected a type"); - next_token(f); return ast_bad_expr(f, token, f->curr_token); } return type; @@ -2798,20 +3047,18 @@ PARSE_SPEC_FUNC(parse_import_spec) { switch (f->curr_token.kind) { case Token_Period: - import_name = f->curr_token; + import_name = advance_token(f); import_name.kind = Token_Ident; - next_token(f); break; case Token_Ident: - import_name = f->curr_token; - next_token(f); + import_name = advance_token(f); break; default: import_name.pos = f->curr_token.pos; break; } - if (import_name.string == "_") { + if (is_blank_ident(import_name)) { syntax_error(import_name, "Illegal import name: `_`"); } @@ -2856,15 +3103,13 @@ PARSE_SPEC_FUNC(parse_foreign_library_spec) { switch (f->curr_token.kind) { case Token_Ident: - lib_name = f->curr_token; - next_token(f); + lib_name = advance_token(f); break; default: lib_name.pos = f->curr_token.pos; break; } - - if (lib_name.string == "_") { + if (is_blank_ident(lib_name)) { syntax_error(lib_name, "Illegal foreign_library name: `_`"); } Token file_path = expect_token(f, Token_String); @@ -2887,15 +3132,14 @@ PARSE_SPEC_FUNC(parse_foreign_library_spec) { switch (f->curr_token.kind) { case Token_Ident: - lib_name = f->curr_token; - next_token(f); + lib_name = advance_token(f); break; default: lib_name.pos = f->curr_token.pos; break; } - if (lib_name.string == "_") { + if (is_blank_ident(lib_name)) { syntax_error(lib_name, "Illegal foreign_library name: `_`"); } Token file_path = expect_token(f, Token_String); @@ -2986,9 +3230,7 @@ AstNode *parse_decl(AstFile *f) { } } - Token token = f->curr_token; - next_token(f); - return parse_gen_decl(f, token, func); + return parse_gen_decl(f, advance_token(f), func); } AstNode *parse_value_decl(AstFile *f, Array<AstNode *> names, CommentGroup docs) { @@ -3002,7 +3244,7 @@ AstNode *parse_value_decl(AstFile *f, Array<AstNode *> names, CommentGroup docs) if (f->curr_token.kind == Token_Eq || f->curr_token.kind == Token_Colon) { - Token sep = f->curr_token; next_token(f); + Token sep = advance_token(f); is_mutable = sep.kind != Token_Colon; values = parse_rhs_expr_list(f); if (values.count > names.count) { @@ -3073,7 +3315,7 @@ AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) { syntax_error(f->curr_token, "You cannot use a simple statement in the file scope"); return ast_bad_stmt(f, f->curr_token, f->curr_token); } - next_token(f); + advance_token(f); Array<AstNode *> rhs = parse_rhs_expr_list(f); if (rhs.count == 0) { syntax_error(token, "No right-hand side in assignment statement."); @@ -3103,7 +3345,7 @@ AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) { switch (next) { case Token_for: case Token_match: { - next_token(f); + advance_token(f); AstNode *name = lhs[0]; AstNode *label = ast_label_decl(f, ast_node_token(name), name); AstNode *stmt = parse_stmt(f); @@ -3135,7 +3377,7 @@ AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) { switch (token.kind) { case Token_Inc: case Token_Dec: - next_token(f); + advance_token(f); return ast_inc_dec_stmt(f, token, lhs[0]); } @@ -3212,8 +3454,7 @@ AstNode *parse_proc_type(AstFile *f, Token proc_token, String *link_name_) { AstNode *parse_var_type(AstFile *f, bool allow_ellipsis, bool allow_type_token) { if (allow_ellipsis && f->curr_token.kind == Token_Ellipsis) { - Token tok = f->curr_token; - next_token(f); + Token tok = advance_token(f); AstNode *type = parse_type_or_ident(f); if (type == nullptr) { error(tok, "variadic field missing type after `...`"); @@ -3254,7 +3495,7 @@ FieldPrefixKind is_token_field_prefix(AstFile *f) { return FieldPrefix_Using; case Token_Hash: { - next_token(f); + advance_token(f); switch (f->curr_token.kind) { case Token_Ident: if (f->curr_token.string == "no_alias") { @@ -3282,9 +3523,9 @@ u32 parse_field_prefixes(AstFile *f) { break; } switch (kind) { - case FieldPrefix_Using: using_count += 1; next_token(f); break; - case FieldPrefix_NoAlias: no_alias_count += 1; next_token(f); break; - case FieldPrefix_CVarArg: c_vararg_count += 1; next_token(f); break; + case FieldPrefix_Using: using_count += 1; advance_token(f); break; + case FieldPrefix_NoAlias: no_alias_count += 1; advance_token(f); break; + case FieldPrefix_CVarArg: c_vararg_count += 1; advance_token(f); break; } } if (using_count > 1) syntax_error(f->curr_token, "Multiple `using` in this field list"); @@ -3358,8 +3599,8 @@ bool parse_expect_field_separator(AstFile *f, AstNode *param) { return true; } if (token.kind == Token_Semicolon) { - next_token(f); error(f->curr_token, "Expected a comma, got a semicolon"); + advance_token(f); return true; } return false; @@ -3372,8 +3613,8 @@ bool parse_expect_struct_separator(AstFile *f, AstNode *param) { } if (token.kind == Token_Colon) { - next_token(f); error(f->curr_token, "Expected a semicolon, got a comma"); + advance_token(f); return true; } @@ -3453,7 +3694,7 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok if (f->curr_token.kind != Token_Comma) { break; } - next_token(f); + advance_token(f); } if (f->curr_token.kind == Token_Colon) { @@ -3555,6 +3796,14 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok } AstNode *parse_type_or_ident(AstFile *f) { +#if 1 + bool prev_allow_type = f->allow_type; + f->allow_type = true; + AstNode *operand = parse_operand(f, true); + AstNode *type = parse_atom_expr(f, operand, true); + f->allow_type = prev_allow_type; + return type; +#else switch (f->curr_token.kind) { case Token_Dollar: { Token token = expect_token(f, Token_Dollar); @@ -3566,8 +3815,7 @@ AstNode *parse_type_or_ident(AstFile *f) { AstNode *i = ast_implicit(f, expect_token(f, Token_type_of)); AstNode *type = parse_call_expr(f, i); while (f->curr_token.kind == Token_Period) { - Token token = f->curr_token; - next_token(f); + Token token = advance_token(f); AstNode *sel = parse_ident(f); type = ast_selector_expr(f, token, type, sel); } @@ -3577,8 +3825,7 @@ AstNode *parse_type_or_ident(AstFile *f) { case Token_Ident: { AstNode *e = parse_ident(f); while (f->curr_token.kind == Token_Period) { - Token token = f->curr_token; - next_token(f); + Token token = advance_token(f); AstNode *sel = parse_ident(f); e = ast_selector_expr(f, token, e, sel); } @@ -3616,8 +3863,7 @@ AstNode *parse_type_or_ident(AstFile *f) { if (f->curr_token.kind == Token_Ellipsis) { count_expr = ast_unary_expr(f, expect_token(f, Token_Ellipsis), nullptr); - } else if (f->curr_token.kind == Token_vector) { - next_token(f); + } else if (allow_token(f, Token_vector)) { if (f->curr_token.kind != Token_CloseBracket) { f->expr_level++; count_expr = parse_expr(f, false); @@ -3626,8 +3872,7 @@ AstNode *parse_type_or_ident(AstFile *f) { syntax_error(f->curr_token, "Vector type missing count"); } is_vector = true; - } else if (f->curr_token.kind == Token_dynamic) { - next_token(f); + } else if (allow_token(f, Token_dynamic)) { expect_token(f, Token_CloseBracket); return ast_dynamic_array_type(f, token, parse_type(f)); } else if (f->curr_token.kind != Token_CloseBracket) { @@ -3806,7 +4051,7 @@ AstNode *parse_type_or_ident(AstFile *f) { if (f->curr_token.kind != Token_Comma) { break; } - next_token(f); + advance_token(f); } close = expect_token(f, Token_CloseBrace); @@ -3815,7 +4060,7 @@ AstNode *parse_type_or_ident(AstFile *f) { } break; case Token_proc: { - Token token = f->curr_token; next_token(f); + Token token = advance_token(f); AstNode *pt = parse_proc_type(f, token, nullptr); if (pt->ProcType.tags != 0) { syntax_error(token, "A procedure type cannot have tags"); @@ -3832,6 +4077,7 @@ AstNode *parse_type_or_ident(AstFile *f) { } return nullptr; +#endif } @@ -3984,7 +4230,7 @@ AstNode *parse_return_stmt(AstFile *f) { f->curr_token.kind == Token_EOF) { break; } - next_token(f); + advance_token(f); } AstNode *end = nullptr; @@ -4061,8 +4307,7 @@ AstNode *parse_for_stmt(AstFile *f) { } } - if (!is_range && f->curr_token.kind == Token_Semicolon) { - next_token(f); + if (!is_range && allow_token(f, Token_Semicolon)) { init = cond; cond = nullptr; if (f->curr_token.kind != Token_Semicolon) { @@ -4291,8 +4536,8 @@ AstNode *parse_stmt(AstFile *f) { case Token_break: case Token_continue: case Token_fallthrough: { + Token token = advance_token(f); AstNode *label = nullptr; - next_token(f); if (token.kind != Token_fallthrough && f->curr_token.kind == Token_Ident) { label = parse_ident(f); @@ -4333,7 +4578,7 @@ AstNode *parse_stmt(AstFile *f) { } break; case Token_push_allocator: { - next_token(f); + advance_token(f); AstNode *body = nullptr; isize prev_level = f->expr_level; f->expr_level = -1; @@ -4350,7 +4595,7 @@ AstNode *parse_stmt(AstFile *f) { } break; case Token_push_context: { - next_token(f); + advance_token(f); AstNode *body = nullptr; isize prev_level = f->expr_level; f->expr_level = -1; @@ -4432,7 +4677,7 @@ AstNode *parse_stmt(AstFile *f) { case Token_Semicolon: s = ast_empty_stmt(f, token); - next_token(f); + advance_token(f); return s; } @@ -4694,9 +4939,7 @@ void parse_file(Parser *p, AstFile *f) { base_dir.len--; } - while (f->curr_token.kind == Token_Comment) { - next_token(f); - } + comsume_comment_groups(f, f->prev_token); f->decls = parse_stmt_list(f); parse_setup_file_decls(p, f, base_dir, f->decls); |