From 5d22204d2dbf686d8b827eca15253914ef9543ab Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Mon, 11 Jul 2022 23:51:57 +0300 Subject: parser: add helpful error for C style container declarations ```zig // a.zig struct Foo { a: u32, }; ``` before: ``` a.zig:1:1: error: expected test, comptime, var decl, or container field, found 'struct' struct Foo { ^ ``` after: ``` a.zig:1:8: error: 'struct Foo' is invalid struct Foo { ^ a.zig:1:8: note: to declare a container do 'const Foo = struct' struct Foo { ^ ``` --- src/Module.zig | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/Module.zig') diff --git a/src/Module.zig b/src/Module.zig index 3c4962c587..aa5cddd35c 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3335,6 +3335,15 @@ pub fn astGenFile(mod: *Module, file: *File) !void { .parent_decl_node = 0, .lazy = .{ .byte_abs = token_starts[file.tree.errors[2].token] }, }, err_msg, "field after declarations here", .{}); + } else if (parse_err.tag == .c_style_container) { + const note = file.tree.errors[1]; + try mod.errNoteNonLazy(.{ + .file_scope = file, + .parent_decl_node = 0, + .lazy = .{ .byte_abs = token_starts[note.token] }, + }, err_msg, "to declare a container do 'const {s} = {s}'", .{ + file.tree.tokenSlice(note.token), note.extra.expected_tag.symbol(), + }); } { -- cgit v1.2.3 From 2a3f3766a437faed13736c1ff505854b6737ae33 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Tue, 12 Jul 2022 10:49:37 +0300 Subject: stage2: handle parser notes in a more general way --- lib/std/zig/parse.zig | 5 +++-- src/Module.zig | 35 +++++++++++++++------------------- src/main.zig | 53 +++++++++++++++------------------------------------ 3 files changed, 33 insertions(+), 60 deletions(-) (limited to 'src/Module.zig') diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index ed59bc687c..96b680a389 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -178,7 +178,6 @@ const Parser = struct { .expected_block_or_assignment, .expected_block_or_expr, .expected_block_or_field, - .expected_container_members, .expected_expr, .expected_expr_or_assignment, .expected_fn, @@ -401,10 +400,12 @@ const Parser = struct { }); try p.warnMsg(.{ .tag = .previous_field, + .is_note = true, .token = last_field, }); try p.warnMsg(.{ .tag = .next_field, + .is_note = true, .token = identifier, }); // Continue parsing; error will be reported later. @@ -985,7 +986,7 @@ const Parser = struct { .keyword_switch => return p.expectSwitchExpr(), .keyword_if => return p.expectIfStatement(), .keyword_enum, .keyword_struct, .keyword_union => { - const identifier = p.tok_i + 2; + const identifier = p.tok_i + 1; if (try p.parseCStyleContainer()) { // Return something so that `expectStatement` is happy. return p.addNode(.{ diff --git a/src/Module.zig b/src/Module.zig index aa5cddd35c..f9cfc5e54e 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3324,26 +3324,21 @@ pub fn astGenFile(mod: *Module, file: *File) !void { .parent_decl_node = 0, .lazy = .{ .byte_abs = byte_abs }, }, err_msg, "invalid byte: '{'}'", .{std.zig.fmtEscapes(source[byte_abs..][0..1])}); - } else if (parse_err.tag == .decl_between_fields) { - try mod.errNoteNonLazy(.{ - .file_scope = file, - .parent_decl_node = 0, - .lazy = .{ .byte_abs = token_starts[file.tree.errors[1].token] }, - }, err_msg, "field before declarations here", .{}); - try mod.errNoteNonLazy(.{ - .file_scope = file, - .parent_decl_node = 0, - .lazy = .{ .byte_abs = token_starts[file.tree.errors[2].token] }, - }, err_msg, "field after declarations here", .{}); - } else if (parse_err.tag == .c_style_container) { - const note = file.tree.errors[1]; - try mod.errNoteNonLazy(.{ - .file_scope = file, - .parent_decl_node = 0, - .lazy = .{ .byte_abs = token_starts[note.token] }, - }, err_msg, "to declare a container do 'const {s} = {s}'", .{ - file.tree.tokenSlice(note.token), note.extra.expected_tag.symbol(), - }); + } + + for (file.tree.errors[1..]) |note| { + if (!note.is_note) break; + + try file.tree.renderError(note, msg.writer()); + err_msg.notes = try mod.gpa.realloc(err_msg.notes, err_msg.notes.len + 1); + err_msg.notes[err_msg.notes.len - 1] = .{ + .src_loc = .{ + .file_scope = file, + .parent_decl_node = 0, + .lazy = .{ .byte_abs = token_starts[note.token] }, + }, + .msg = msg.toOwnedSlice(), + }; } { diff --git a/src/main.zig b/src/main.zig index 59152d8928..3d77fc242a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4367,7 +4367,7 @@ fn printErrsMsgToStdErr( defer text_buf.deinit(); const writer = text_buf.writer(); try tree.renderError(parse_error, writer); - const text = text_buf.items; + const text = try arena.dupe(u8, text_buf.items); var notes_buffer: [2]Compilation.AllErrors.Message = undefined; var notes_len: usize = 0; @@ -4388,49 +4388,26 @@ fn printErrsMsgToStdErr( }, }; notes_len += 1; - } else if (parse_error.tag == .decl_between_fields) { - const prev_loc = tree.tokenLocation(0, parse_errors[i + 1].token); - notes_buffer[0] = .{ - .src = .{ - .src_path = path, - .msg = "field before declarations here", - .byte_offset = @intCast(u32, prev_loc.line_start), - .line = @intCast(u32, prev_loc.line), - .column = @intCast(u32, prev_loc.column), - .source_line = tree.source[prev_loc.line_start..prev_loc.line_end], - }, - }; - const next_loc = tree.tokenLocation(0, parse_errors[i + 2].token); - notes_buffer[1] = .{ - .src = .{ - .src_path = path, - .msg = "field after declarations here", - .byte_offset = @intCast(u32, next_loc.line_start), - .line = @intCast(u32, next_loc.line), - .column = @intCast(u32, next_loc.column), - .source_line = tree.source[next_loc.line_start..next_loc.line_end], - }, - }; - notes_len = 2; - i += 2; - } else if (parse_error.tag == .c_style_container) { - const note = tree.errors[i + 1]; + } + + for (parse_errors[i + 1 ..]) |note| { + if (!note.is_note) break; - const prev_loc = tree.tokenLocation(0, parse_errors[i + 1].token); - notes_buffer[0] = .{ + text_buf.items.len = 0; + try tree.renderError(note, writer); + const note_loc = tree.tokenLocation(0, note.token); + notes_buffer[notes_len] = .{ .src = .{ .src_path = path, - .msg = try std.fmt.allocPrint(arena, "to declare a container do 'const {s} = {s}'", .{ - tree.tokenSlice(note.token), note.extra.expected_tag.symbol(), - }), - .byte_offset = @intCast(u32, prev_loc.line_start), - .line = @intCast(u32, prev_loc.line), - .column = @intCast(u32, prev_loc.column), - .source_line = tree.source[prev_loc.line_start..prev_loc.line_end], + .msg = try arena.dupe(u8, text_buf.items), + .byte_offset = @intCast(u32, note_loc.line_start), + .line = @intCast(u32, note_loc.line), + .column = @intCast(u32, note_loc.column), + .source_line = tree.source[note_loc.line_start..note_loc.line_end], }, }; - notes_len = 1; i += 1; + notes_len += 1; } const extra_offset = tree.errorOffset(parse_error); -- cgit v1.2.3