diff options
Diffstat (limited to 'src/parser.cpp')
| -rw-r--r-- | src/parser.cpp | 84 |
1 files changed, 73 insertions, 11 deletions
diff --git a/src/parser.cpp b/src/parser.cpp index 3f189e96b..63099cf55 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -106,6 +106,16 @@ Token ast_token(Ast *node) { return empty_token; } +Token token_end_of_line(AstFile *f, Token tok) { + u8 const *start = f->tokenizer.start + tok.pos.offset; + u8 const *s = start; + while (*s && *s != '\n' && s < f->tokenizer.end) { + s += 1; + } + tok.pos.column += cast(i32)(s - start) - 1; + return tok; +} + isize ast_node_size(AstKind kind) { return align_formula_isize(gb_size_of(AstCommonStuff) + ast_variant_sizes[kind], gb_align_of(void *)); @@ -1379,6 +1389,17 @@ bool allow_token(AstFile *f, TokenKind kind) { return false; } +Token expect_closing_brace_of_field_list(AstFile *f) { + Token token = f->curr_token; + if (allow_token(f, Token_CloseBrace)) { + return token; + } + if (allow_token(f, Token_Semicolon)) { + String p = token_to_string(token); + syntax_error(token_end_of_line(f, f->prev_token), "Expected a comma, got a %.*s", LIT(p)); + } + return expect_token(f, Token_CloseBrace); +} bool is_blank_ident(String str) { if (str.len == 1) { @@ -1451,7 +1472,9 @@ Token expect_closing(AstFile *f, TokenKind kind, String context) { if (f->curr_token.kind != kind && f->curr_token.kind == Token_Semicolon && f->curr_token.string == "\n") { - syntax_error(f->curr_token, "Missing ',' before newline in %.*s", LIT(context)); + Token tok = f->prev_token; + tok.pos.column += cast(i32)tok.string.len; + syntax_error(tok, "Missing ',' before newline in %.*s", LIT(context)); advance_token(f); } return expect_token(f, kind); @@ -1512,16 +1535,42 @@ bool is_semicolon_optional_for_node(AstFile *f, Ast *s) { return false; } +void expect_semicolon_newline_error(AstFile *f, Token const &token, Ast *s) { + if (build_context.strict_style && false) { + if (f->curr_proc != nullptr && token.string == "\n") { + switch (token.kind) { + case Token_CloseBrace: + case Token_CloseParen: + case Token_else: + case Token_EOF: + return; + } + if (s != nullptr) { + if (is_semicolon_optional_for_node(f, s)) { + return; + } + } + + Token tok = token; + tok.pos.column -= 1; + syntax_error(tok, "Expected ';', got newline"); + } + } +} + void expect_semicolon(AstFile *f, Ast *s) { + Token prev_token = {}; + if (allow_token(f, Token_Semicolon)) { + expect_semicolon_newline_error(f, f->prev_token, s); return; } - Token prev_token = f->prev_token; + prev_token = f->prev_token; if (prev_token.kind == Token_Semicolon) { + expect_semicolon_newline_error(f, f->prev_token, s); return; } - if (s != nullptr) { bool insert_semi = (f->tokenizer.flags & TokenizerFlag_InsertSemicolon) != 0; if (insert_semi) { @@ -2241,9 +2290,9 @@ Ast *parse_operand(AstFile *f, bool lhs) { Token open = expect_token_after(f, Token_OpenBrace, "struct"); - isize name_count = 0; + isize name_count = 0; Ast *fields = parse_struct_field_list(f, &name_count); - Token close = expect_token(f, Token_CloseBrace); + Token close = expect_closing_brace_of_field_list(f); Slice<Ast *> decls = {}; if (fields != nullptr) { @@ -2328,7 +2377,7 @@ Ast *parse_operand(AstFile *f, bool lhs) { } } - Token close = expect_token(f, Token_CloseBrace); + Token close = expect_closing_brace_of_field_list(f); return ast_union_type(f, token, variants, polymorphic_params, align, no_nil, maybe, where_token, where_clauses); } break; @@ -2342,7 +2391,7 @@ Ast *parse_operand(AstFile *f, bool lhs) { Token open = expect_token(f, Token_OpenBrace); Array<Ast *> values = parse_element_list(f); - Token close = expect_token(f, Token_CloseBrace); + Token close = expect_closing_brace_of_field_list(f); return ast_enum_type(f, token, base_type, values); } break; @@ -2435,7 +2484,7 @@ Ast *parse_operand(AstFile *f, bool lhs) { expect_token(f, Token_Comma); Ast *constraints_string = parse_expr(f, false); allow_token(f, Token_Comma); - Token close = expect_token(f, Token_CloseBrace); + Token close = expect_closing_brace_of_field_list(f); return ast_inline_asm_expr(f, token, open, close, param_types, return_type, asm_string, constraints_string, has_side_effects, is_align_stack, dialect); } @@ -3370,7 +3419,7 @@ bool parse_expect_field_separator(AstFile *f, Ast *param) { } if (token.kind == Token_Semicolon) { String p = token_to_string(token); - syntax_error(f->curr_token, "Expected a comma, got a %.*s", LIT(p)); + syntax_error(token_end_of_line(f, f->prev_token), "Expected a comma, got a %.*s", LIT(p)); advance_token(f); return true; } @@ -3648,6 +3697,18 @@ Ast *parse_body(AstFile *f) { return ast_block_stmt(f, stmts, open, close); } +bool parse_control_statement_semicolon_separator(AstFile *f) { + Token tok = peek_token(f); + if (tok.kind != Token_OpenBrace) { + return allow_token(f, Token_Semicolon); + } + if (f->curr_token.string == ";") { + return allow_token(f, Token_Semicolon); + } + return false; +} + + Ast *parse_if_stmt(AstFile *f) { if (f->curr_proc == nullptr) { syntax_error(f->curr_token, "You cannot use an if statement in the file scope"); @@ -3669,7 +3730,7 @@ Ast *parse_if_stmt(AstFile *f) { cond = parse_expr(f, false); } else { init = parse_simple_stmt(f, StmtAllowFlag_None); - if (allow_token(f, Token_Semicolon)) { + if (parse_control_statement_semicolon_separator(f)) { cond = parse_expr(f, false); } else { cond = convert_stmt_to_expr(f, init, str_lit("boolean expression")); @@ -3977,7 +4038,7 @@ Ast *parse_switch_stmt(AstFile *f) { tag = parse_simple_stmt(f, StmtAllowFlag_In); if (tag->kind == Ast_AssignStmt && tag->AssignStmt.op.kind == Token_in) { is_type_switch = true; - } else if (allow_token(f, Token_Semicolon)) { + } else if (parse_control_statement_semicolon_separator(f)) { init = tag; tag = nullptr; if (f->curr_token.kind != Token_OpenBrace) { @@ -3986,6 +4047,7 @@ Ast *parse_switch_stmt(AstFile *f) { } } } + skip_possible_newline(f); open = expect_token(f, Token_OpenBrace); while (f->curr_token.kind == Token_case) { |