diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 351162bec0..b1441d5b25 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -166,7 +166,6 @@ pub const Error = union(enum) { ExpectedDerefOrUnwrap: ExpectedDerefOrUnwrap, ExpectedSuffixOp: ExpectedSuffixOp, DeclBetweenFields: DeclBetweenFields, - MissingComma: MissingComma, InvalidAnd: InvalidAnd, pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void { @@ -217,7 +216,6 @@ pub const Error = union(enum) { .ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream), .ExpectedSuffixOp => |*x| return x.render(tokens, stream), .DeclBetweenFields => |*x| return x.render(tokens, stream), - .MissingComma => |*x| return x.render(tokens, stream), .InvalidAnd => |*x| return x.render(tokens, stream), } } @@ -270,7 +268,6 @@ pub const Error = union(enum) { .ExpectedDerefOrUnwrap => |x| return x.token, .ExpectedSuffixOp => |x| return x.token, .DeclBetweenFields => |x| return x.token, - .MissingComma => |x| return x.token, .InvalidAnd => |x| return x.token, } } @@ -318,7 +315,6 @@ pub const Error = union(enum) { pub const ExtraVolatileQualifier = SimpleError("Extra volatile qualifier"); pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier"); pub const DeclBetweenFields = SimpleError("Declarations are not allowed between container fields"); - pub const MissingComma = SimpleError("Expected comma between items"); pub const InvalidAnd = SimpleError("`&&` is invalid. Note that `and` is boolean AND."); pub const ExpectedCall = struct { @@ -926,7 +922,7 @@ pub const Node = struct { if (i < 1) return node; i -= 1; }, - .Invalid => unreachable, + .Invalid => {}, } if (self.body_node) |body_node| { @@ -948,7 +944,7 @@ pub const Node = struct { if (self.body_node) |body_node| return body_node.lastToken(); switch (self.return_type) { .Explicit, .InferErrorSet => |node| return node.lastToken(), - .Invalid => unreachable, + .Invalid => |tok| return tok, } } }; diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 74945b1b33..a269dc616c 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -78,7 +78,7 @@ fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error /// / KEYWORD_pub? ContainerField COMMA ContainerMembers /// / KEYWORD_pub? ContainerField /// / -fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error!Node.Root.DeclList { +fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !Node.Root.DeclList { var list = Node.Root.DeclList.init(arena); var field_state: union(enum) { @@ -136,7 +136,7 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All if (parseTopLevelDecl(arena, it, tree) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.ParseError => { - // try again + findNextContainerMember(it); continue; }, }) |node| { @@ -324,7 +324,7 @@ fn findNextStmt(it: *TokenIterator) void { } /// Eat a multiline container doc comment -fn parseContainerDocComments(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error!?*Node { +fn parseContainerDocComments(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { var lines = Node.DocComment.LineList.init(arena); while (eatToken(it, .ContainerDocComment)) |line| { try lines.push(line); @@ -384,7 +384,7 @@ fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?* /// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) /// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl /// / KEYWORD_usingnamespace Expr SEMICOLON -fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*Node { +fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { var lib_name: ?*Node = null; const extern_export_inline_token = blk: { if (eatToken(it, .Keyword_export)) |token| break :blk token; @@ -397,13 +397,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!? break :blk null; }; - if (parseFnProto(arena, it, tree) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - error.ParseError => { - findNextContainerMember(it); - return error.ParseError; - }, - }) |node| { + if (try parseFnProto(arena, it, tree)) |node| { const fn_node = node.cast(Node.FnProto).?; fn_node.*.extern_export_inline_token = extern_export_inline_token; fn_node.*.lib_name = lib_name; @@ -413,7 +407,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!? // since parseBlock only return error.ParseError on // a missing '}' we can assume this function was // supposed to end here. - error.ParseError => null, + error.ParseError => return node, }) |body_node| { fn_node.body_node = body_node; return node; @@ -437,14 +431,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!? const thread_local_token = eatToken(it, .Keyword_threadlocal); - if (parseVarDecl(arena, it, tree) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - error.ParseError => { - // try to skip to next decl - findNextContainerMember(it); - return error.ParseError; - }, - }) |node| { + if (try parseVarDecl(arena, it, tree)) |node| { var var_decl = node.cast(Node.VarDecl).?; var_decl.*.thread_local_token = thread_local_token; var_decl.*.comptime_token = null; @@ -469,14 +456,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!? return error.ParseError; } - return parseUse(arena, it, tree) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - error.ParseError => { - // try to skip to next decl - findNextContainerMember(it); - return error.ParseError; - }, - }; + return try parseUse(arena, it, tree); } /// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) @@ -2926,7 +2906,7 @@ fn ListParseFn(comptime L: type, comptime nodeParseFn: var) ParseFn(L) { // this is likely just a missing comma, // continue parsing this list and give an error try tree.errors.push(.{ - .MissingComma = .{ .token = it.index }, + .ExpectedToken = .{ .token = it.index, .expected_id = .Comma }, }); }, } diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index f92cc5a222..6adc44a5b7 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -32,8 +32,8 @@ test "recovery: missing comma" { \\ } \\} , &[_]Error{ - .MissingComma, - .MissingComma, + .ExpectedToken, + .ExpectedToken, .InvalidAnd, .InvalidToken, }); @@ -2983,7 +2983,6 @@ test "zig fmt: extern without container keyword returns error" { , &[_]Error{ .ExpectedExpr, .ExpectedVarDeclOrFn, - .ExpectedContainerMembers, }); } diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 64f2f77f6c..9ca6d4450c 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -13,6 +13,9 @@ pub const Error = error{ /// Returns whether anything changed pub fn render(allocator: *mem.Allocator, stream: var, tree: *ast.Tree) (@TypeOf(stream).Error || Error)!bool { + // cannot render an invalid tree + std.debug.assert(tree.errors.len == 0); + // make a passthrough stream that checks whether something changed const MyStream = struct { const MyStream = @This();