Commit be392777b7
Changed files (3)
lib
lib/std/zig/ast.zig
@@ -165,6 +165,7 @@ pub const Error = union(enum) {
ExpectedDerefOrUnwrap: ExpectedDerefOrUnwrap,
ExpectedSuffixOp: ExpectedSuffixOp,
DeclBetweenFields: DeclBetweenFields,
+ MissingComma: MissingComma,
pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void {
switch (self.*) {
@@ -213,6 +214,7 @@ pub const Error = union(enum) {
.ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream),
.ExpectedSuffixOp => |*x| return x.render(tokens, stream),
.DeclBetweenFields => |*x| return x.render(tokens, stream),
+ .MissingComma => |*x| return x.render(tokens, stream),
}
}
@@ -263,6 +265,7 @@ pub const Error = union(enum) {
.ExpectedDerefOrUnwrap => |x| return x.token,
.ExpectedSuffixOp => |x| return x.token,
.DeclBetweenFields => |x| return x.token,
+ .MissingComma => |x| return x.token,
}
}
@@ -308,6 +311,7 @@ pub const Error = union(enum) {
pub const ExtraVolatileQualifier = SimpleError("Extra volatile qualifier");
pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier");
pub const DeclBetweenFields = SimpleError("Declarations are not allowed between container fields");
+ pub const MissingComma = SimpleError("Expected comma between items");
pub const ExpectedCall = struct {
node: *Node,
lib/std/zig/parse.zig
@@ -1083,7 +1083,14 @@ fn parseBlock(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
var statements = Node.Block.StatementList.init(arena);
while (true) {
- const statement = (try parseStatement(arena, it, tree)) orelse break;
+ const statement = (parseStatement(arena, it, tree) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.ParseError => {
+ // try to skip to the next statement
+ findToken(it, .Semicolon);
+ continue;
+ },
+ }) orelse break;
try statements.push(statement);
}
@@ -2816,7 +2823,24 @@ fn ListParseFn(comptime L: type, comptime nodeParseFn: var) ParseFn(L) {
var list = L.init(arena);
while (try nodeParseFn(arena, it, tree)) |node| {
try list.push(node);
- if (eatToken(it, .Comma) == null) break;
+
+ const token = nextToken(it);
+ switch (token.ptr.id) {
+ .Comma => {},
+ // all possible delimiters
+ .Colon, .RParen, .RBrace, .RBracket => {
+ putBackToken(it, token.index);
+ break;
+ },
+ else => {
+ // this is likely just a missing comma,
+ // continue parsing this list and give an error
+ try tree.errors.push(.{
+ .MissingComma = .{ .token = token.index },
+ });
+ putBackToken(it, token.index);
+ },
+ }
}
return list;
}
lib/std/zig/parser_test.zig
@@ -6,6 +6,30 @@ test "zig fmt: fault tolerant parsing" {
.ExpectedInlinable,
.ExpectedInlinable,
});
+ try testError(
+ \\test "" {
+ \\ foo + +;
+ \\ inline;
+ \\}
+ , &[_]Error{
+ .InvalidToken,
+ .ExpectedInlinable,
+ });
+ try testError(
+ \\test "" {
+ \\ switch (foo) {
+ \\ 2 => {}
+ \\ 3 => {}
+ \\ else => {
+ \\ inline;
+ \\ }
+ \\ }
+ \\}
+ , &[_]Error{
+ .MissingComma,
+ .MissingComma,
+ .ExpectedInlinable,
+ });
}
test "zig fmt: top-level fields" {