From 89f2923a8aad5119b1506c3b8e08464e132c228e Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 14 May 2020 11:19:50 +0300 Subject: [PATCH] recover from missing semicolon --- lib/std/zig/parse.zig | 16 +++++++++++++--- lib/std/zig/parser_test.zig | 17 +++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index c16dba4a11..24bb164685 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -667,7 +667,12 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No if (try parseLabeledStatement(arena, it, tree)) |node| return node; if (try parseSwitchExpr(arena, it, tree)) |node| return node; if (try parseAssignExpr(arena, it, tree)) |node| { - _ = try expectToken(it, tree, .Semicolon); + _ = eatToken(it, .Semicolon) orelse { + try tree.errors.push(.{ + .ExpectedToken = .{ .token = it.index, .expected_id = .Semicolon }, + }); + // pretend we saw a semicolon and continue parsing + }; return node; } @@ -911,7 +916,12 @@ fn parseWhileStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No fn parseBlockExprStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { if (try parseBlockExpr(arena, it, tree)) |node| return node; if (try parseAssignExpr(arena, it, tree)) |node| { - _ = try expectToken(it, tree, .Semicolon); + _ = eatToken(it, .Semicolon) orelse { + try tree.errors.push(.{ + .ExpectedToken = .{ .token = it.index, .expected_id = .Semicolon }, + }); + // pretend we saw a semicolon and continue parsing + }; return node; } return null; @@ -3072,7 +3082,7 @@ fn parseDocComment(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.D } /// Eat a single-line doc comment on the same line as another node -fn parseAppendedDocComment(arena: *Allocator, it: *TokenIterator, tree: *Tree, after_token: TokenIndex) Allocator.Error!?*Node.DocComment { +fn parseAppendedDocComment(arena: *Allocator, it: *TokenIterator, tree: *Tree, after_token: TokenIndex) !?*Node.DocComment { const comment_token = eatToken(it, .DocComment) orelse return null; if (tree.tokensOnSameLine(after_token, comment_token)) { const node = try arena.create(Node.DocComment); diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 34c61b6bb4..a367c2ff0b 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -102,6 +102,23 @@ test "recovery: invalid extern/inline" { }); } +test "recovery: missing semicolon" { + try testError( + \\test "" { + \\ comptime a && b + \\ c && d + \\ @foo + \\} + , &[_]Error{ + .InvalidAnd, + .ExpectedToken, + .InvalidAnd, + .ExpectedToken, + .ExpectedParamList, + .ExpectedToken, + }); +} + test "zig fmt: top-level fields" { try testCanonical( \\a: did_you_know,