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

This commit is contained in:
Veikka Tuominen 2021-02-22 10:04:05 +02:00
parent 621ad241d6
commit 67dac2936c
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
3 changed files with 54 additions and 12 deletions

View File

@ -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,

View File

@ -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 {

View File

@ -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;