aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2021-02-22 10:04:05 +0200
committerVeikka Tuominen <git@vexu.eu>2021-02-22 10:04:05 +0200
commit67dac2936cb1fc2ce1d3ea00a5c8e574921aded3 (patch)
tree5b24fa50a184ef3ef4d6ae8f53c76eec4b1282ca
parent621ad241d6dfbde60ee8a5b1d0dcd7d9cf29f8f3 (diff)
downloadzig-67dac2936cb1fc2ce1d3ea00a5c8e574921aded3.tar.gz
zig-67dac2936cb1fc2ce1d3ea00a5c8e574921aded3.zip
parser: warn on missing for loop payload, recover from invalid global error set access
-rw-r--r--lib/std/zig/ast.zig6
-rw-r--r--lib/std/zig/parse.zig44
-rw-r--r--lib/std/zig/parser_test.zig16
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;