authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-02-17 14:22:34+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-02-17 20:51:26+02:00
log92f276781417d7e710081470d97606e26cf764d6
treecc5a4864a9e1fca1c177d1b8f3f83877d2c9ae29
parentc9dde10f8629c3ad2234f6220990b1dd70bac807

parser: add error for missing colon before continue expr

If a '(' is found where the continue expression was expected and it is on the same line as the previous token issue an error about missing colon before the continue expression.

4 files changed, 32 insertions(+), 5 deletions(-)

lib/std/zig/Ast.zig+5-2
...@@ -300,6 +300,9 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {...@@ -300,6 +300,9 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
300 .varargs_nonfinal => {300 .varargs_nonfinal => {
301 return stream.writeAll("function prototype has parameter after varargs");301 return stream.writeAll("function prototype has parameter after varargs");
302 },302 },
303 .expected_continue_expr => {
304 return stream.writeAll("expected ':' before while continue expression");
305 },
303306
304 .expected_semi_after_decl => {307 .expected_semi_after_decl => {
305 return stream.writeAll("expected ';' after declaration");308 return stream.writeAll("expected ';' after declaration");
...@@ -2467,6 +2470,7 @@ pub const full = struct {...@@ -2467,6 +2470,7 @@ pub const full = struct {
24672470
2468pub const Error = struct {2471pub const Error = struct {
2469 tag: Tag,2472 tag: Tag,
2473 /// True if `token` points to the token before the token causing an issue.
2470 token_is_prev: bool = false,2474 token_is_prev: bool = false,
2471 token: TokenIndex,2475 token: TokenIndex,
2472 extra: union {2476 extra: union {
...@@ -2513,8 +2517,7 @@ pub const Error = struct {...@@ -2513,8 +2517,7 @@ pub const Error = struct {
2513 same_line_doc_comment,2517 same_line_doc_comment,
2514 unattached_doc_comment,2518 unattached_doc_comment,
2515 varargs_nonfinal,2519 varargs_nonfinal,
25162520 expected_continue_expr,
2517 // these have `token` set to token after which a semicolon was expected
2518 expected_semi_after_decl,2521 expected_semi_after_decl,
2519 expected_semi_after_stmt,2522 expected_semi_after_stmt,
2520 expected_comma_after_field,2523 expected_comma_after_field,
lib/std/zig/parse.zig+6-1
...@@ -2943,7 +2943,12 @@ const Parser = struct {...@@ -2943,7 +2943,12 @@ const Parser = struct {
29432943
2944 /// WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN2944 /// WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN
2945 fn parseWhileContinueExpr(p: *Parser) !Node.Index {2945 fn parseWhileContinueExpr(p: *Parser) !Node.Index {
2946 _ = p.eatToken(.colon) orelse return null_node;2946 _ = p.eatToken(.colon) orelse {
2947 if (p.token_tags[p.tok_i] == .l_paren and
2948 p.tokensOnSameLine(p.tok_i - 1, p.tok_i))
2949 return p.fail(.expected_continue_expr);
2950 return null_node;
2951 };
2947 _ = try p.expectToken(.l_paren);2952 _ = try p.expectToken(.l_paren);
2948 const node = try p.parseAssignExpr();2953 const node = try p.parseAssignExpr();
2949 if (node == 0) return p.fail(.expected_expr_or_assignment);2954 if (node == 0) return p.fail(.expected_expr_or_assignment);
lib/std/zig/parser_test.zig+19
...@@ -5018,6 +5018,25 @@ test "zig fmt: make single-line if no trailing comma" {...@@ -5018,6 +5018,25 @@ test "zig fmt: make single-line if no trailing comma" {
5018 );5018 );
5019}5019}
50205020
5021test "zig fmt: while continue expr" {
5022 try testCanonical(
5023 \\test {
5024 \\ while (i > 0)
5025 \\ (i * 2);
5026 \\}
5027 \\
5028 );
5029 try testError(
5030 \\test {
5031 \\ while (i > 0) (i -= 1) {
5032 \\ print("test123", .{});
5033 \\ }
5034 \\}
5035 , &[_]Error{
5036 .expected_continue_expr,
5037 });
5038}
5039
5021test "zig fmt: error for invalid bit range" {5040test "zig fmt: error for invalid bit range" {
5022 try testError(5041 try testError(
5023 \\var x: []align(0:0:0)u8 = bar;5042 \\var x: []align(0:0:0)u8 = bar;
test/compile_errors.zig+2-2
...@@ -4869,11 +4869,11 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -4869,11 +4869,11 @@ pub fn addCases(ctx: *TestContext) !void {
4869 \\export fn entry() void {4869 \\export fn entry() void {
4870 \\ while(true) {}4870 \\ while(true) {}
4871 \\ var good = {};4871 \\ var good = {};
4872 \\ while(true) ({})4872 \\ while(true) 1
4873 \\ var bad = {};4873 \\ var bad = {};
4874 \\}4874 \\}
4875 , &[_][]const u8{4875 , &[_][]const u8{
4876 "tmp.zig:4:21: error: expected ';' or 'else' after statement",4876 "tmp.zig:4:18: error: expected ';' or 'else' after statement",
4877 });4877 });
48784878
4879 ctx.objErrStage1("implicit semicolon - while expression",4879 ctx.objErrStage1("implicit semicolon - while expression",