Commit e07b467c7c

Vexu <git@vexu.eu>
2020-05-20 10:34:31
fix missing compile error on while/for missing block
1 parent 69ff89f
Changed files (3)
lib/std/zig/ast.zig
@@ -13,7 +13,6 @@ pub const Tree = struct {
     token_ids: []const Token.Id,
     token_locs: []const Token.Loc,
     errors: []const Error,
-    /// undefined on parse error (when errors field is not empty)
     root_node: *Node.Root,
 
     arena: std.heap.ArenaAllocator.State,
lib/std/zig/parse.zig
@@ -878,34 +878,32 @@ const Parser = struct {
             return node;
         }
 
-        if (try p.parseAssignExpr()) |assign_expr| {
-            for_prefix.body = assign_expr;
-
-            if (p.eatToken(.Semicolon) != null) return node;
-
-            if (p.eatToken(.Keyword_else)) |else_token| {
-                const statement_node = try p.expectNode(parseStatement, .{
-                    .ExpectedStatement = .{ .token = p.tok_i },
-                });
+        for_prefix.body = try p.expectNode(parseAssignExpr, .{
+            .ExpectedBlockOrAssignment = .{ .token = p.tok_i },
+        });
 
-                const else_node = try p.arena.allocator.create(Node.Else);
-                else_node.* = .{
-                    .else_token = else_token,
-                    .payload = null,
-                    .body = statement_node,
-                };
-                for_prefix.@"else" = else_node;
-                return node;
-            }
+        if (p.eatToken(.Semicolon) != null) return node;
 
-            try p.errors.append(p.gpa, .{
-                .ExpectedSemiOrElse = .{ .token = p.tok_i },
+        if (p.eatToken(.Keyword_else)) |else_token| {
+            const statement_node = try p.expectNode(parseStatement, .{
+                .ExpectedStatement = .{ .token = p.tok_i },
             });
 
+            const else_node = try p.arena.allocator.create(Node.Else);
+            else_node.* = .{
+                .else_token = else_token,
+                .payload = null,
+                .body = statement_node,
+            };
+            for_prefix.@"else" = else_node;
             return node;
         }
 
-        return null;
+        try p.errors.append(p.gpa, .{
+            .ExpectedSemiOrElse = .{ .token = p.tok_i },
+        });
+
+        return node;
     }
 
     /// WhileStatement
@@ -939,36 +937,35 @@ const Parser = struct {
             return node;
         }
 
-        if (try p.parseAssignExpr()) |assign_expr_node| {
-            while_prefix.body = assign_expr_node;
-
-            if (p.eatToken(.Semicolon) != null) return node;
 
-            if (p.eatToken(.Keyword_else)) |else_token| {
-                const payload = try p.parsePayload();
+        while_prefix.body = try p.expectNode(parseAssignExpr, .{
+            .ExpectedBlockOrAssignment = .{ .token = p.tok_i },
+        });
 
-                const statement_node = try p.expectNode(parseStatement, .{
-                    .ExpectedStatement = .{ .token = p.tok_i },
-                });
+        if (p.eatToken(.Semicolon) != null) return node;
 
-                const else_node = try p.arena.allocator.create(Node.Else);
-                else_node.* = .{
-                    .else_token = else_token,
-                    .payload = payload,
-                    .body = statement_node,
-                };
-                while_prefix.@"else" = else_node;
-                return node;
-            }
+        if (p.eatToken(.Keyword_else)) |else_token| {
+            const payload = try p.parsePayload();
 
-            try p.errors.append(p.gpa, .{
-                .ExpectedSemiOrElse = .{ .token = p.tok_i },
+            const statement_node = try p.expectNode(parseStatement, .{
+                .ExpectedStatement = .{ .token = p.tok_i },
             });
 
+            const else_node = try p.arena.allocator.create(Node.Else);
+            else_node.* = .{
+                .else_token = else_token,
+                .payload = payload,
+                .body = statement_node,
+            };
+            while_prefix.@"else" = else_node;
             return node;
         }
 
-        return null;
+        try p.errors.append(p.gpa, .{
+            .ExpectedSemiOrElse = .{ .token = p.tok_i },
+        });
+
+        return node;
     }
 
     /// BlockExprStatement
lib/std/zig/parser_test.zig
@@ -210,6 +210,19 @@ test "recovery: invalid comptime" {
     });
 }
 
+test "recovery: missing block after for/while loops" {
+    try testError(
+        \\test "" { while (foo) }
+    , &[_]Error{
+        .ExpectedBlockOrAssignment,
+    });
+    try testError(
+        \\test "" { for (foo) |bar| }
+    , &[_]Error{
+        .ExpectedBlockOrAssignment,
+    });
+}
+
 test "zig fmt: if statment" {
     try testCanonical(
         \\test "" {