From 67dac2936cb1fc2ce1d3ea00a5c8e574921aded3 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Mon, 22 Feb 2021 10:04:05 +0200 Subject: parser: warn on missing for loop payload, recover from invalid global error set access --- lib/std/zig/ast.zig | 6 ++++++ lib/std/zig/parse.zig | 44 ++++++++++++++++++++++++++++++++------------ lib/std/zig/parser_test.zig | 16 ++++++++++++++++ 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index c81386cca4..72846b333c 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -253,6 +253,11 @@ pub const Tree = struct { token_tags[parse_error.token].symbol(), }); }, + .expected_loop_payload => { + return stream.print("expected loop payload, found '{s}'", .{ + token_tags[parse_error.token].symbol(), + }); + }, .extra_align_qualifier => { return stream.writeAll("extra align qualifier"); }, @@ -2332,6 +2337,7 @@ pub const Error = struct { expected_type_expr, expected_var_decl, expected_var_decl_or_fn, + expected_loop_payload, extra_align_qualifier, extra_allowzero_qualifier, extra_const_qualifier, diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 90d634c1fc..fd142b8765 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -1052,7 +1052,8 @@ const Parser = struct { _ = try p.expectToken(.l_paren); const array_expr = try p.expectExpr(); _ = try p.expectToken(.r_paren); - _ = try p.parsePtrIndexPayload(); + const found_payload = try p.parsePtrIndexPayload(); + if (found_payload == 0) try p.warn(.expected_loop_payload); // TODO propose to change the syntax so that semicolons are always required // inside while statements, even if there is an `else`. @@ -2067,7 +2068,8 @@ const Parser = struct { _ = try p.expectToken(.l_paren); const array_expr = try p.expectExpr(); _ = try p.expectToken(.r_paren); - _ = try p.parsePtrIndexPayload(); + const found_payload = try p.parsePtrIndexPayload(); + if (found_payload == 0) try p.warn(.expected_loop_payload); const then_expr = try p.expectExpr(); const else_token = p.eatToken(.keyword_else) orelse { @@ -2672,6 +2674,16 @@ const Parser = struct { }, }), }, + .keyword_inline => { + p.tok_i += 1; + switch (p.token_tags[p.tok_i]) { + .keyword_for => return p.parseForTypeExpr(), + .keyword_while => return p.parseWhileTypeExpr(), + else => return p.fail(.expected_inlinable), + } + }, + .keyword_for => return p.parseForTypeExpr(), + .keyword_while => return p.parseWhileTypeExpr(), .period => switch (p.token_tags[p.tok_i + 1]) { .identifier => return p.addNode(.{ .tag = .enum_literal, @@ -2879,14 +2891,21 @@ const Parser = struct { }, }); }, - else => return p.addNode(.{ - .tag = .error_value, - .main_token = p.nextToken(), - .data = .{ - .lhs = try p.expectToken(.period), - .rhs = try p.expectToken(.identifier), - }, - }), + else => { + const main_token = p.nextToken(); + const period = p.eatToken(.period); + if (period == null) try p.warnExpected(.period); + const identifier = p.eatToken(.identifier); + if (identifier == null) try p.warnExpected(.identifier); + return p.addNode(.{ + .tag = .error_value, + .main_token = main_token, + .data = .{ + .lhs = period orelse 0, + .rhs = identifier orelse 0, + }, + }); + }, }, .l_paren => return p.addNode(.{ .tag = .grouped_expression, @@ -2913,9 +2932,10 @@ const Parser = struct { fn parseForTypeExpr(p: *Parser) !Node.Index { const for_token = p.eatToken(.keyword_for) orelse return null_node; _ = try p.expectToken(.l_paren); - const array_expr = try p.expectTypeExpr(); + const array_expr = try p.expectExpr(); _ = try p.expectToken(.r_paren); - _ = try p.parsePtrIndexPayload(); + const found_payload = try p.parsePtrIndexPayload(); + if (found_payload == 0) try p.warn(.expected_loop_payload); const then_expr = try p.expectExpr(); const else_token = p.eatToken(.keyword_else) orelse { diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 375f12a3f5..3802427af2 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -4215,6 +4215,8 @@ test "recovery: invalid global error set access" { \\} , &[_]Error{ .expected_token, + .expected_token, + .invalid_and, }); } @@ -4273,6 +4275,20 @@ test "recovery: missing block after for/while loops" { }); } +test "recovery: missing for payload" { + try testError( + \\comptime { + \\ const a = for(a) {}; + \\ const a: for(a) {}; + \\ for(a) {} + \\} + , &[_]Error{ + .expected_loop_payload, + .expected_loop_payload, + .expected_loop_payload, + }); +} + const std = @import("std"); const mem = std.mem; const warn = std.debug.warn; -- cgit v1.2.3