authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-22 10:04:05+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-22 10:04:05+02:00
log67dac2936cb1fc2ce1d3ea00a5c8e574921aded3
tree5b24fa50a184ef3ef4d6ae8f53c76eec4b1282ca
parent621ad241d6dfbde60ee8a5b1d0dcd7d9cf29f8f3
signaturelock-open Commit is signed but in an unrecognized format.

parser: warn on missing for loop payload, recover from invalid global error set access


3 files changed, 54 insertions(+), 12 deletions(-)

lib/std/zig/ast.zig+6
......@@ -253,6 +253,11 @@ pub const Tree = struct {
253253 token_tags[parse_error.token].symbol(),
254254 });
255255 },
256 .expected_loop_payload => {
257 return stream.print("expected loop payload, found '{s}'", .{
258 token_tags[parse_error.token].symbol(),
259 });
260 },
256261 .extra_align_qualifier => {
257262 return stream.writeAll("extra align qualifier");
258263 },
......@@ -2332,6 +2337,7 @@ pub const Error = struct {
23322337 expected_type_expr,
23332338 expected_var_decl,
23342339 expected_var_decl_or_fn,
2340 expected_loop_payload,
23352341 extra_align_qualifier,
23362342 extra_allowzero_qualifier,
23372343 extra_const_qualifier,
lib/std/zig/parse.zig+32-12
......@@ -1052,7 +1052,8 @@ const Parser = struct {
10521052 _ = try p.expectToken(.l_paren);
10531053 const array_expr = try p.expectExpr();
10541054 _ = try p.expectToken(.r_paren);
1055 _ = try p.parsePtrIndexPayload();
1055 const found_payload = try p.parsePtrIndexPayload();
1056 if (found_payload == 0) try p.warn(.expected_loop_payload);
10561057
10571058 // TODO propose to change the syntax so that semicolons are always required
10581059 // inside while statements, even if there is an `else`.
......@@ -2067,7 +2068,8 @@ const Parser = struct {
20672068 _ = try p.expectToken(.l_paren);
20682069 const array_expr = try p.expectExpr();
20692070 _ = try p.expectToken(.r_paren);
2070 _ = try p.parsePtrIndexPayload();
2071 const found_payload = try p.parsePtrIndexPayload();
2072 if (found_payload == 0) try p.warn(.expected_loop_payload);
20712073
20722074 const then_expr = try p.expectExpr();
20732075 const else_token = p.eatToken(.keyword_else) orelse {
......@@ -2672,6 +2674,16 @@ const Parser = struct {
26722674 },
26732675 }),
26742676 },
2677 .keyword_inline => {
2678 p.tok_i += 1;
2679 switch (p.token_tags[p.tok_i]) {
2680 .keyword_for => return p.parseForTypeExpr(),
2681 .keyword_while => return p.parseWhileTypeExpr(),
2682 else => return p.fail(.expected_inlinable),
2683 }
2684 },
2685 .keyword_for => return p.parseForTypeExpr(),
2686 .keyword_while => return p.parseWhileTypeExpr(),
26752687 .period => switch (p.token_tags[p.tok_i + 1]) {
26762688 .identifier => return p.addNode(.{
26772689 .tag = .enum_literal,
......@@ -2879,14 +2891,21 @@ const Parser = struct {
28792891 },
28802892 });
28812893 },
2882 else => return p.addNode(.{
2883 .tag = .error_value,
2884 .main_token = p.nextToken(),
2885 .data = .{
2886 .lhs = try p.expectToken(.period),
2887 .rhs = try p.expectToken(.identifier),
2888 },
2889 }),
2894 else => {
2895 const main_token = p.nextToken();
2896 const period = p.eatToken(.period);
2897 if (period == null) try p.warnExpected(.period);
2898 const identifier = p.eatToken(.identifier);
2899 if (identifier == null) try p.warnExpected(.identifier);
2900 return p.addNode(.{
2901 .tag = .error_value,
2902 .main_token = main_token,
2903 .data = .{
2904 .lhs = period orelse 0,
2905 .rhs = identifier orelse 0,
2906 },
2907 });
2908 },
28902909 },
28912910 .l_paren => return p.addNode(.{
28922911 .tag = .grouped_expression,
......@@ -2913,9 +2932,10 @@ const Parser = struct {
29132932 fn parseForTypeExpr(p: *Parser) !Node.Index {
29142933 const for_token = p.eatToken(.keyword_for) orelse return null_node;
29152934 _ = try p.expectToken(.l_paren);
2916 const array_expr = try p.expectTypeExpr();
2935 const array_expr = try p.expectExpr();
29172936 _ = try p.expectToken(.r_paren);
2918 _ = try p.parsePtrIndexPayload();
2937 const found_payload = try p.parsePtrIndexPayload();
2938 if (found_payload == 0) try p.warn(.expected_loop_payload);
29192939
29202940 const then_expr = try p.expectExpr();
29212941 const else_token = p.eatToken(.keyword_else) orelse {
lib/std/zig/parser_test.zig+16
......@@ -4215,6 +4215,8 @@ test "recovery: invalid global error set access" {
42154215 \\}
42164216 , &[_]Error{
42174217 .expected_token,
4218 .expected_token,
4219 .invalid_and,
42184220 });
42194221}
42204222
......@@ -4273,6 +4275,20 @@ test "recovery: missing block after for/while loops" {
42734275 });
42744276}
42754277
4278test "recovery: missing for payload" {
4279 try testError(
4280 \\comptime {
4281 \\ const a = for(a) {};
4282 \\ const a: for(a) {};
4283 \\ for(a) {}
4284 \\}
4285 , &[_]Error{
4286 .expected_loop_payload,
4287 .expected_loop_payload,
4288 .expected_loop_payload,
4289 });
4290}
4291
42764292const std = @import("std");
42774293const mem = std.mem;
42784294const warn = std.debug.warn;