diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/std/zig/ast.zig | 1 | ||||
| -rw-r--r-- | lib/std/zig/parse.zig | 81 | ||||
| -rw-r--r-- | lib/std/zig/parser_test.zig | 13 |
3 files changed, 52 insertions, 43 deletions
diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 91aaf29096..4d63011266 100644 --- a/lib/std/zig/ast.zig +++ b/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, diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 612f2b54ad..ebf074ba4f 100644 --- a/lib/std/zig/parse.zig +++ b/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 diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 25fc48e46d..a7a5511889 100644 --- a/lib/std/zig/parser_test.zig +++ b/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 "" { |
