fix missing compile error on while/for missing block

This commit is contained in:
Vexu 2020-05-20 11:34:31 +03:00
parent 69ff89fd12
commit e07b467c7c
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
3 changed files with 52 additions and 43 deletions

View File

@ -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,

View File

@ -878,34 +878,32 @@ const Parser = struct {
return node;
}
if (try p.parseAssignExpr()) |assign_expr| {
for_prefix.body = assign_expr;
for_prefix.body = try p.expectNode(parseAssignExpr, .{
.ExpectedBlockOrAssignment = .{ .token = p.tok_i },
});
if (p.eatToken(.Semicolon) != null) return node;
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 },
});
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;
}
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;
while_prefix.body = try p.expectNode(parseAssignExpr, .{
.ExpectedBlockOrAssignment = .{ .token = p.tok_i },
});
if (p.eatToken(.Keyword_else)) |else_token| {
const payload = try p.parsePayload();
if (p.eatToken(.Semicolon) != null) return node;
const statement_node = try p.expectNode(parseStatement, .{
.ExpectedStatement = .{ .token = p.tok_i },
});
if (p.eatToken(.Keyword_else)) |else_token| {
const payload = try p.parsePayload();
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;
}
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

View File

@ -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 "" {