Commit c3b76d0913

Vexu <git@vexu.eu>
2020-05-13 23:16:56
recover from invalid builtin/async call
1 parent 1f81887
Changed files (3)
lib/std/zig/ast.zig
@@ -926,6 +926,7 @@ pub const Node = struct {
                     if (i < 1) return node;
                     i -= 1;
                 },
+                .Invalid => unreachable,
             }
 
             if (self.body_node) |body_node| {
lib/std/zig/parse.zig
@@ -172,6 +172,7 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All
                 .ExpectedPubItem = .{ .token = it.index },
             });
             // ignore this pub
+            continue;
         }
 
         if (parseContainerField(arena, it, tree) catch |err| switch (err) {
@@ -1017,7 +1018,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
         const node = try arena.create(Node.ControlFlowExpression);
         node.* = .{
             .ltoken = token,
-            .kind = Node.ControlFlowExpression.Kind{ .Break = label },
+            .kind = .{ .Break = label },
             .rhs = expr_node,
         };
         return &node.base;
@@ -1053,7 +1054,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
         const node = try arena.create(Node.ControlFlowExpression);
         node.* = .{
             .ltoken = token,
-            .kind = Node.ControlFlowExpression.Kind{ .Continue = label },
+            .kind = .{ .Continue = label },
             .rhs = null,
         };
         return &node.base;
@@ -1077,7 +1078,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
         const node = try arena.create(Node.ControlFlowExpression);
         node.* = .{
             .ltoken = token,
-            .kind = Node.ControlFlowExpression.Kind.Return,
+            .kind = .Return,
             .rhs = expr_node,
         };
         return &node.base;
@@ -1322,7 +1323,8 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
             try tree.errors.push(.{
                 .ExpectedParamList = .{ .token = it.index },
             });
-            return null;
+            // ignore this, continue parsing
+            return res;
         };
         const node = try arena.create(Node.SuffixOp);
         node.* = .{
@@ -2908,7 +2910,13 @@ fn parseBuiltinCall(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
         try tree.errors.push(.{
             .ExpectedParamList = .{ .token = it.index },
         });
-        return error.ParseError;
+
+        // lets pretend this was an identifier so we can continue parsing
+        const node = try arena.create(Node.Identifier);
+        node.* = .{
+            .token = token,
+        };
+        return &node.base;
     };
     const node = try arena.create(Node.BuiltinCall);
     node.* = .{
lib/std/zig/parser_test.zig
@@ -67,19 +67,22 @@ test "recovery: continue after invalid decl" {
         \\fn foo {
         \\    inline;
         \\}
-        \\test "" {
-        \\    a && b;
+        \\pub test "" {
+        \\    async a && b;
         \\}
     , &[_]Error{
         .ExpectedToken,
+        .ExpectedPubItem,
+        .ExpectedParamList,
         .InvalidAnd,
     });
     try testError(
         \\threadlocal test "" {
-        \\    a && b;
+        \\    @a && b;
         \\}
     , &[_]Error{
         .ExpectedVarDecl,
+        .ExpectedParamList,
         .InvalidAnd,
     });
 }