Commit 92f2767814
Changed files (4)
lib
lib/std/zig/Ast.zig
@@ -300,6 +300,9 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
.varargs_nonfinal => {
return stream.writeAll("function prototype has parameter after varargs");
},
+ .expected_continue_expr => {
+ return stream.writeAll("expected ':' before while continue expression");
+ },
.expected_semi_after_decl => {
return stream.writeAll("expected ';' after declaration");
@@ -2467,6 +2470,7 @@ pub const full = struct {
pub const Error = struct {
tag: Tag,
+ /// True if `token` points to the token before the token causing an issue.
token_is_prev: bool = false,
token: TokenIndex,
extra: union {
@@ -2513,8 +2517,7 @@ pub const Error = struct {
same_line_doc_comment,
unattached_doc_comment,
varargs_nonfinal,
-
- // these have `token` set to token after which a semicolon was expected
+ expected_continue_expr,
expected_semi_after_decl,
expected_semi_after_stmt,
expected_comma_after_field,
lib/std/zig/parse.zig
@@ -2943,7 +2943,12 @@ const Parser = struct {
/// WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN
fn parseWhileContinueExpr(p: *Parser) !Node.Index {
- _ = p.eatToken(.colon) orelse return null_node;
+ _ = p.eatToken(.colon) orelse {
+ if (p.token_tags[p.tok_i] == .l_paren and
+ p.tokensOnSameLine(p.tok_i - 1, p.tok_i))
+ return p.fail(.expected_continue_expr);
+ return null_node;
+ };
_ = try p.expectToken(.l_paren);
const node = try p.parseAssignExpr();
if (node == 0) return p.fail(.expected_expr_or_assignment);
lib/std/zig/parser_test.zig
@@ -5018,6 +5018,25 @@ test "zig fmt: make single-line if no trailing comma" {
);
}
+test "zig fmt: while continue expr" {
+ try testCanonical(
+ \\test {
+ \\ while (i > 0)
+ \\ (i * 2);
+ \\}
+ \\
+ );
+ try testError(
+ \\test {
+ \\ while (i > 0) (i -= 1) {
+ \\ print("test123", .{});
+ \\ }
+ \\}
+ , &[_]Error{
+ .expected_continue_expr,
+ });
+}
+
test "zig fmt: error for invalid bit range" {
try testError(
\\var x: []align(0:0:0)u8 = bar;
test/compile_errors.zig
@@ -4869,11 +4869,11 @@ pub fn addCases(ctx: *TestContext) !void {
\\export fn entry() void {
\\ while(true) {}
\\ var good = {};
- \\ while(true) ({})
+ \\ while(true) 1
\\ var bad = {};
\\}
, &[_][]const u8{
- "tmp.zig:4:21: error: expected ';' or 'else' after statement",
+ "tmp.zig:4:18: error: expected ';' or 'else' after statement",
});
ctx.objErrStage1("implicit semicolon - while expression",