continue parsing after missing commas and invalid statements

This commit is contained in:
Vexu 2020-05-13 17:21:27 +03:00
parent 91358f3092
commit be392777b7
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
3 changed files with 54 additions and 2 deletions

View File

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

View File

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

View File

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