authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-02-13 13:18:30+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-02-13 13:46:58+02:00
log6456af5a45cc12c0cd28d957dfedc72c369a157e
tree4a90d06dc7053134224bc6187cd06aee03efaa4b
parentddd6de86f7eb71814d3605d3e0ea9ed01d075613

parser: make missing comma errors point to the end of the previous token


2 files changed, 71 insertions(+), 52 deletions(-)

lib/std/zig/Ast.zig+29-6
......@@ -70,6 +70,13 @@ pub fn errorOffset(tree:Ast, error_tag: Error.Tag, token: TokenIndex) u32 {
7070 return switch (error_tag) {
7171 .expected_semi_after_decl,
7272 .expected_semi_after_stmt,
73 .expected_comma_after_field,
74 .expected_comma_after_arg,
75 .expected_comma_after_param,
76 .expected_comma_after_initializer,
77 .expected_comma_after_switch_prong,
78 .expected_semi_or_else,
79 .expected_semi_or_lbrace,
7380 => @intCast(u32, tree.tokenSlice(token).len),
7481 else => 0,
7582 };
......@@ -227,14 +234,10 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
227234 });
228235 },
229236 .expected_semi_or_else => {
230 return stream.print("expected ';' or 'else', found '{s}'", .{
231 token_tags[parse_error.token].symbol(),
232 });
237 return stream.writeAll("expected ';' or 'else' after statement");
233238 },
234239 .expected_semi_or_lbrace => {
235 return stream.print("expected ';' or '{{', found '{s}'", .{
236 token_tags[parse_error.token].symbol(),
237 });
240 return stream.writeAll("expected ';' or block after function prototype");
238241 },
239242 .expected_statement => {
240243 return stream.print("expected statement, found '{s}'", .{
......@@ -323,6 +326,21 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
323326 .expected_semi_after_stmt => {
324327 return stream.writeAll("expected ';' after statement");
325328 },
329 .expected_comma_after_field => {
330 return stream.writeAll("expected ',' after field");
331 },
332 .expected_comma_after_arg => {
333 return stream.writeAll("expected ',' after argument");
334 },
335 .expected_comma_after_param => {
336 return stream.writeAll("expected ',' after parameter");
337 },
338 .expected_comma_after_initializer => {
339 return stream.writeAll("expected ',' after initializer");
340 },
341 .expected_comma_after_switch_prong => {
342 return stream.writeAll("expected ',' after switch prong");
343 },
326344
327345 .expected_token => {
328346 const found_tag = token_tags[parse_error.token];
......@@ -2516,6 +2534,11 @@ pub const Error = struct {
25162534 // these have `token` set to token after which a semicolon was expected
25172535 expected_semi_after_decl,
25182536 expected_semi_after_stmt,
2537 expected_comma_after_field,
2538 expected_comma_after_arg,
2539 expected_comma_after_param,
2540 expected_comma_after_initializer,
2541 expected_comma_after_switch_prong,
25192542
25202543 /// `expected_tag` is populated.
25212544 expected_token,
lib/std/zig/parse.zig+42-46
......@@ -160,6 +160,12 @@ const Parser = struct {
160160 .extra = .{ .expected_tag = expected_token },
161161 });
162162 }
163
164 fn warnExpectedAfter(p: *Parser, error_tag: AstError.Tag) error{OutOfMemory}!void {
165 @setCold(true);
166 try p.warnMsg(.{ .tag = error_tag, .token = p.tok_i - 1 });
167 }
168
163169 fn warnMsg(p: *Parser, msg: Ast.Error) error{OutOfMemory}!void {
164170 @setCold(true);
165171 try p.errors.append(p.gpa, msg);
......@@ -258,7 +264,7 @@ const Parser = struct {
258264 }
259265 // There is not allowed to be a decl after a field with no comma.
260266 // Report error but recover parser.
261 try p.warnExpected(.comma);
267 try p.warnExpectedAfter(.expected_comma_after_field);
262268 p.findNextContainerMember();
263269 }
264270 },
......@@ -361,7 +367,7 @@ const Parser = struct {
361367 }
362368 // There is not allowed to be a decl after a field with no comma.
363369 // Report error but recover parser.
364 try p.warnExpected(.comma);
370 try p.warnExpectedAfter(.expected_comma_after_field);
365371 p.findNextContainerMember();
366372 }
367373 },
......@@ -573,7 +579,7 @@ const Parser = struct {
573579 // Since parseBlock only return error.ParseError on
574580 // a missing '}' we can assume this function was
575581 // supposed to end here.
576 try p.warn(.expected_semi_or_lbrace);
582 try p.warnExpectedAfter(.expected_semi_or_lbrace);
577583 return null_node;
578584 },
579585 }
......@@ -984,7 +990,7 @@ const Parser = struct {
984990 };
985991 _ = p.eatToken(.keyword_else) orelse {
986992 if (else_required) {
987 try p.warn(.expected_semi_or_else);
993 try p.warnExpectedAfter(.expected_semi_or_else);
988994 }
989995 return p.addNode(.{
990996 .tag = .if_simple,
......@@ -1079,7 +1085,7 @@ const Parser = struct {
10791085 };
10801086 _ = p.eatToken(.keyword_else) orelse {
10811087 if (else_required) {
1082 try p.warn(.expected_semi_or_else);
1088 try p.warnExpectedAfter(.expected_semi_or_else);
10831089 }
10841090 return p.addNode(.{
10851091 .tag = .for_simple,
......@@ -1154,7 +1160,7 @@ const Parser = struct {
11541160 };
11551161 _ = p.eatToken(.keyword_else) orelse {
11561162 if (else_required) {
1157 try p.warn(.expected_semi_or_else);
1163 try p.warnExpectedAfter(.expected_semi_or_else);
11581164 }
11591165 if (cont_expr == 0) {
11601166 return p.addNode(.{
......@@ -2038,7 +2044,7 @@ const Parser = struct {
20382044 },
20392045 .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
20402046 // Likely just a missing comma; give error but continue parsing.
2041 else => try p.warnExpected(.comma),
2047 else => try p.warnExpectedAfter(.expected_comma_after_initializer),
20422048 }
20432049 if (p.eatToken(.r_brace)) |_| break;
20442050 const next = try p.expectFieldInit();
......@@ -2079,7 +2085,7 @@ const Parser = struct {
20792085 },
20802086 .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
20812087 // Likely just a missing comma; give error but continue parsing.
2082 else => try p.warnExpected(.comma),
2088 else => try p.warnExpectedAfter(.expected_comma_after_initializer),
20832089 }
20842090 }
20852091 const comma = (p.token_tags[p.tok_i - 2] == .comma);
......@@ -2158,7 +2164,7 @@ const Parser = struct {
21582164 },
21592165 .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren),
21602166 // Likely just a missing comma; give error but continue parsing.
2161 else => try p.warnExpected(.comma),
2167 else => try p.warnExpectedAfter(.expected_comma_after_arg),
21622168 }
21632169 }
21642170 const comma = (p.token_tags[p.tok_i - 2] == .comma);
......@@ -2214,7 +2220,7 @@ const Parser = struct {
22142220 },
22152221 .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren),
22162222 // Likely just a missing comma; give error but continue parsing.
2217 else => try p.warnExpected(.comma),
2223 else => try p.warnExpectedAfter(.expected_comma_after_arg),
22182224 }
22192225 }
22202226 const comma = (p.token_tags[p.tok_i - 2] == .comma);
......@@ -2455,7 +2461,7 @@ const Parser = struct {
24552461 },
24562462 .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
24572463 // Likely just a missing comma; give error but continue parsing.
2458 else => try p.warnExpected(.comma),
2464 else => try p.warnExpectedAfter(.expected_comma_after_initializer),
24592465 }
24602466 if (p.eatToken(.r_brace)) |_| break;
24612467 const next = try p.expectFieldInit();
......@@ -2507,7 +2513,7 @@ const Parser = struct {
25072513 },
25082514 .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
25092515 // Likely just a missing comma; give error but continue parsing.
2510 else => try p.warnExpected(.comma),
2516 else => try p.warnExpectedAfter(.expected_comma_after_initializer),
25112517 }
25122518 }
25132519 const comma = (p.token_tags[p.tok_i - 2] == .comma);
......@@ -2568,7 +2574,7 @@ const Parser = struct {
25682574 },
25692575 .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
25702576 // Likely just a missing comma; give error but continue parsing.
2571 else => try p.warnExpected(.comma),
2577 else => try p.warnExpectedAfter(.expected_comma_after_field),
25722578 }
25732579 }
25742580 return p.addNode(.{
......@@ -3383,7 +3389,24 @@ const Parser = struct {
33833389
33843390 /// SwitchProngList <- (SwitchProng COMMA)* SwitchProng?
33853391 fn parseSwitchProngList(p: *Parser) !Node.SubRange {
3386 return ListParseFn(parseSwitchProng)(p);
3392 const scratch_top = p.scratch.items.len;
3393 defer p.scratch.shrinkRetainingCapacity(scratch_top);
3394
3395 while (true) {
3396 const item = try parseSwitchProng(p);
3397 if (item == 0) break;
3398
3399 try p.scratch.append(p.gpa, item);
3400
3401 switch (p.token_tags[p.tok_i]) {
3402 .comma => p.tok_i += 1,
3403 // All possible delimiters.
3404 .colon, .r_paren, .r_brace, .r_bracket => break,
3405 // Likely just a missing comma; give error but continue parsing.
3406 else => try p.warnExpectedAfter(.expected_comma_after_switch_prong),
3407 }
3408 }
3409 return p.listToSpan(p.scratch.items[scratch_top..]);
33873410 }
33883411
33893412 /// ParamDeclList <- (ParamDecl COMMA)* ParamDecl?
......@@ -3409,7 +3432,7 @@ const Parser = struct {
34093432 },
34103433 .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren),
34113434 // Likely just a missing comma; give error but continue parsing.
3412 else => try p.warnExpected(.comma),
3435 else => try p.warnExpectedAfter(.expected_comma_after_param),
34133436 }
34143437 }
34153438 if (varargs == .nonfinal) {
......@@ -3423,33 +3446,6 @@ const Parser = struct {
34233446 };
34243447 }
34253448
3426 const NodeParseFn = fn (p: *Parser) Error!Node.Index;
3427
3428 fn ListParseFn(comptime nodeParseFn: anytype) (fn (p: *Parser) Error!Node.SubRange) {
3429 return struct {
3430 pub fn parse(p: *Parser) Error!Node.SubRange {
3431 const scratch_top = p.scratch.items.len;
3432 defer p.scratch.shrinkRetainingCapacity(scratch_top);
3433
3434 while (true) {
3435 const item = try nodeParseFn(p);
3436 if (item == 0) break;
3437
3438 try p.scratch.append(p.gpa, item);
3439
3440 switch (p.token_tags[p.tok_i]) {
3441 .comma => p.tok_i += 1,
3442 // All possible delimiters.
3443 .colon, .r_paren, .r_brace, .r_bracket => break,
3444 // Likely just a missing comma; give error but continue parsing.
3445 else => try p.warnExpected(.comma),
3446 }
3447 }
3448 return p.listToSpan(p.scratch.items[scratch_top..]);
3449 }
3450 }.parse;
3451 }
3452
34533449 /// FnCallArguments <- LPAREN ExprList RPAREN
34543450 /// ExprList <- (Expr COMMA)* Expr?
34553451 fn parseBuiltinCall(p: *Parser) !Node.Index {
......@@ -3480,7 +3476,7 @@ const Parser = struct {
34803476 break;
34813477 },
34823478 // Likely just a missing comma; give error but continue parsing.
3483 else => try p.warnExpected(.comma),
3479 else => try p.warnExpectedAfter(.expected_comma_after_arg),
34843480 }
34853481 }
34863482 const comma = (p.token_tags[p.tok_i - 2] == .comma);
......@@ -3576,7 +3572,7 @@ const Parser = struct {
35763572 }
35773573
35783574 /// KEYWORD_if LPAREN Expr RPAREN PtrPayload? Body (KEYWORD_else Payload? Body)?
3579 fn parseIf(p: *Parser, bodyParseFn: NodeParseFn) !Node.Index {
3575 fn parseIf(p: *Parser, bodyParseFn: fn (p: *Parser) Error!Node.Index) !Node.Index {
35803576 const if_token = p.eatToken(.keyword_if) orelse return null_node;
35813577 _ = try p.expectToken(.l_paren);
35823578 const condition = try p.expectExpr();
......@@ -3664,12 +3660,12 @@ const Parser = struct {
36643660 }
36653661 }
36663662
3667 fn expectSemicolon(p: *Parser, tag: AstError.Tag, recoverable: bool) Error!void {
3663 fn expectSemicolon(p: *Parser, error_tag: AstError.Tag, recoverable: bool) Error!void {
36683664 if (p.token_tags[p.tok_i] == .semicolon) {
36693665 _ = p.nextToken();
36703666 return;
36713667 }
3672 try p.warnMsg(.{ .tag = tag, .token = p.tok_i - 1 });
3668 try p.warnExpectedAfter(error_tag);
36733669 if (!recoverable) return error.ParseError;
36743670 }
36753671