Commit 6456af5a45
lib/std/zig/Ast.zig
@@ -70,6 +70,13 @@ pub fn errorOffset(tree:Ast, error_tag: Error.Tag, token: TokenIndex) u32 {
return switch (error_tag) {
.expected_semi_after_decl,
.expected_semi_after_stmt,
+ .expected_comma_after_field,
+ .expected_comma_after_arg,
+ .expected_comma_after_param,
+ .expected_comma_after_initializer,
+ .expected_comma_after_switch_prong,
+ .expected_semi_or_else,
+ .expected_semi_or_lbrace,
=> @intCast(u32, tree.tokenSlice(token).len),
else => 0,
};
@@ -227,14 +234,10 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
});
},
.expected_semi_or_else => {
- return stream.print("expected ';' or 'else', found '{s}'", .{
- token_tags[parse_error.token].symbol(),
- });
+ return stream.writeAll("expected ';' or 'else' after statement");
},
.expected_semi_or_lbrace => {
- return stream.print("expected ';' or '{{', found '{s}'", .{
- token_tags[parse_error.token].symbol(),
- });
+ return stream.writeAll("expected ';' or block after function prototype");
},
.expected_statement => {
return stream.print("expected statement, found '{s}'", .{
@@ -323,6 +326,21 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
.expected_semi_after_stmt => {
return stream.writeAll("expected ';' after statement");
},
+ .expected_comma_after_field => {
+ return stream.writeAll("expected ',' after field");
+ },
+ .expected_comma_after_arg => {
+ return stream.writeAll("expected ',' after argument");
+ },
+ .expected_comma_after_param => {
+ return stream.writeAll("expected ',' after parameter");
+ },
+ .expected_comma_after_initializer => {
+ return stream.writeAll("expected ',' after initializer");
+ },
+ .expected_comma_after_switch_prong => {
+ return stream.writeAll("expected ',' after switch prong");
+ },
.expected_token => {
const found_tag = token_tags[parse_error.token];
@@ -2516,6 +2534,11 @@ pub const Error = struct {
// these have `token` set to token after which a semicolon was expected
expected_semi_after_decl,
expected_semi_after_stmt,
+ expected_comma_after_field,
+ expected_comma_after_arg,
+ expected_comma_after_param,
+ expected_comma_after_initializer,
+ expected_comma_after_switch_prong,
/// `expected_tag` is populated.
expected_token,
lib/std/zig/parse.zig
@@ -160,6 +160,12 @@ const Parser = struct {
.extra = .{ .expected_tag = expected_token },
});
}
+
+ fn warnExpectedAfter(p: *Parser, error_tag: AstError.Tag) error{OutOfMemory}!void {
+ @setCold(true);
+ try p.warnMsg(.{ .tag = error_tag, .token = p.tok_i - 1 });
+ }
+
fn warnMsg(p: *Parser, msg: Ast.Error) error{OutOfMemory}!void {
@setCold(true);
try p.errors.append(p.gpa, msg);
@@ -258,7 +264,7 @@ const Parser = struct {
}
// There is not allowed to be a decl after a field with no comma.
// Report error but recover parser.
- try p.warnExpected(.comma);
+ try p.warnExpectedAfter(.expected_comma_after_field);
p.findNextContainerMember();
}
},
@@ -361,7 +367,7 @@ const Parser = struct {
}
// There is not allowed to be a decl after a field with no comma.
// Report error but recover parser.
- try p.warnExpected(.comma);
+ try p.warnExpectedAfter(.expected_comma_after_field);
p.findNextContainerMember();
}
},
@@ -573,7 +579,7 @@ const Parser = struct {
// Since parseBlock only return error.ParseError on
// a missing '}' we can assume this function was
// supposed to end here.
- try p.warn(.expected_semi_or_lbrace);
+ try p.warnExpectedAfter(.expected_semi_or_lbrace);
return null_node;
},
}
@@ -984,7 +990,7 @@ const Parser = struct {
};
_ = p.eatToken(.keyword_else) orelse {
if (else_required) {
- try p.warn(.expected_semi_or_else);
+ try p.warnExpectedAfter(.expected_semi_or_else);
}
return p.addNode(.{
.tag = .if_simple,
@@ -1079,7 +1085,7 @@ const Parser = struct {
};
_ = p.eatToken(.keyword_else) orelse {
if (else_required) {
- try p.warn(.expected_semi_or_else);
+ try p.warnExpectedAfter(.expected_semi_or_else);
}
return p.addNode(.{
.tag = .for_simple,
@@ -1154,7 +1160,7 @@ const Parser = struct {
};
_ = p.eatToken(.keyword_else) orelse {
if (else_required) {
- try p.warn(.expected_semi_or_else);
+ try p.warnExpectedAfter(.expected_semi_or_else);
}
if (cont_expr == 0) {
return p.addNode(.{
@@ -2038,7 +2044,7 @@ const Parser = struct {
},
.colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
// Likely just a missing comma; give error but continue parsing.
- else => try p.warnExpected(.comma),
+ else => try p.warnExpectedAfter(.expected_comma_after_initializer),
}
if (p.eatToken(.r_brace)) |_| break;
const next = try p.expectFieldInit();
@@ -2079,7 +2085,7 @@ const Parser = struct {
},
.colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
// Likely just a missing comma; give error but continue parsing.
- else => try p.warnExpected(.comma),
+ else => try p.warnExpectedAfter(.expected_comma_after_initializer),
}
}
const comma = (p.token_tags[p.tok_i - 2] == .comma);
@@ -2158,7 +2164,7 @@ const Parser = struct {
},
.colon, .r_brace, .r_bracket => return p.failExpected(.r_paren),
// Likely just a missing comma; give error but continue parsing.
- else => try p.warnExpected(.comma),
+ else => try p.warnExpectedAfter(.expected_comma_after_arg),
}
}
const comma = (p.token_tags[p.tok_i - 2] == .comma);
@@ -2214,7 +2220,7 @@ const Parser = struct {
},
.colon, .r_brace, .r_bracket => return p.failExpected(.r_paren),
// Likely just a missing comma; give error but continue parsing.
- else => try p.warnExpected(.comma),
+ else => try p.warnExpectedAfter(.expected_comma_after_arg),
}
}
const comma = (p.token_tags[p.tok_i - 2] == .comma);
@@ -2455,7 +2461,7 @@ const Parser = struct {
},
.colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
// Likely just a missing comma; give error but continue parsing.
- else => try p.warnExpected(.comma),
+ else => try p.warnExpectedAfter(.expected_comma_after_initializer),
}
if (p.eatToken(.r_brace)) |_| break;
const next = try p.expectFieldInit();
@@ -2507,7 +2513,7 @@ const Parser = struct {
},
.colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
// Likely just a missing comma; give error but continue parsing.
- else => try p.warnExpected(.comma),
+ else => try p.warnExpectedAfter(.expected_comma_after_initializer),
}
}
const comma = (p.token_tags[p.tok_i - 2] == .comma);
@@ -2568,7 +2574,7 @@ const Parser = struct {
},
.colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
// Likely just a missing comma; give error but continue parsing.
- else => try p.warnExpected(.comma),
+ else => try p.warnExpectedAfter(.expected_comma_after_field),
}
}
return p.addNode(.{
@@ -3383,7 +3389,24 @@ const Parser = struct {
/// SwitchProngList <- (SwitchProng COMMA)* SwitchProng?
fn parseSwitchProngList(p: *Parser) !Node.SubRange {
- return ListParseFn(parseSwitchProng)(p);
+ const scratch_top = p.scratch.items.len;
+ defer p.scratch.shrinkRetainingCapacity(scratch_top);
+
+ while (true) {
+ const item = try parseSwitchProng(p);
+ if (item == 0) break;
+
+ try p.scratch.append(p.gpa, item);
+
+ switch (p.token_tags[p.tok_i]) {
+ .comma => p.tok_i += 1,
+ // All possible delimiters.
+ .colon, .r_paren, .r_brace, .r_bracket => break,
+ // Likely just a missing comma; give error but continue parsing.
+ else => try p.warnExpectedAfter(.expected_comma_after_switch_prong),
+ }
+ }
+ return p.listToSpan(p.scratch.items[scratch_top..]);
}
/// ParamDeclList <- (ParamDecl COMMA)* ParamDecl?
@@ -3409,7 +3432,7 @@ const Parser = struct {
},
.colon, .r_brace, .r_bracket => return p.failExpected(.r_paren),
// Likely just a missing comma; give error but continue parsing.
- else => try p.warnExpected(.comma),
+ else => try p.warnExpectedAfter(.expected_comma_after_param),
}
}
if (varargs == .nonfinal) {
@@ -3423,33 +3446,6 @@ const Parser = struct {
};
}
- const NodeParseFn = fn (p: *Parser) Error!Node.Index;
-
- fn ListParseFn(comptime nodeParseFn: anytype) (fn (p: *Parser) Error!Node.SubRange) {
- return struct {
- pub fn parse(p: *Parser) Error!Node.SubRange {
- const scratch_top = p.scratch.items.len;
- defer p.scratch.shrinkRetainingCapacity(scratch_top);
-
- while (true) {
- const item = try nodeParseFn(p);
- if (item == 0) break;
-
- try p.scratch.append(p.gpa, item);
-
- switch (p.token_tags[p.tok_i]) {
- .comma => p.tok_i += 1,
- // All possible delimiters.
- .colon, .r_paren, .r_brace, .r_bracket => break,
- // Likely just a missing comma; give error but continue parsing.
- else => try p.warnExpected(.comma),
- }
- }
- return p.listToSpan(p.scratch.items[scratch_top..]);
- }
- }.parse;
- }
-
/// FnCallArguments <- LPAREN ExprList RPAREN
/// ExprList <- (Expr COMMA)* Expr?
fn parseBuiltinCall(p: *Parser) !Node.Index {
@@ -3480,7 +3476,7 @@ const Parser = struct {
break;
},
// Likely just a missing comma; give error but continue parsing.
- else => try p.warnExpected(.comma),
+ else => try p.warnExpectedAfter(.expected_comma_after_arg),
}
}
const comma = (p.token_tags[p.tok_i - 2] == .comma);
@@ -3576,7 +3572,7 @@ const Parser = struct {
}
/// KEYWORD_if LPAREN Expr RPAREN PtrPayload? Body (KEYWORD_else Payload? Body)?
- fn parseIf(p: *Parser, bodyParseFn: NodeParseFn) !Node.Index {
+ fn parseIf(p: *Parser, bodyParseFn: fn (p: *Parser) Error!Node.Index) !Node.Index {
const if_token = p.eatToken(.keyword_if) orelse return null_node;
_ = try p.expectToken(.l_paren);
const condition = try p.expectExpr();
@@ -3664,12 +3660,12 @@ const Parser = struct {
}
}
- fn expectSemicolon(p: *Parser, tag: AstError.Tag, recoverable: bool) Error!void {
+ fn expectSemicolon(p: *Parser, error_tag: AstError.Tag, recoverable: bool) Error!void {
if (p.token_tags[p.tok_i] == .semicolon) {
_ = p.nextToken();
return;
}
- try p.warnMsg(.{ .tag = tag, .token = p.tok_i - 1 });
+ try p.warnExpectedAfter(error_tag);
if (!recoverable) return error.ParseError;
}