fix infinite loop

findToken wasn't as generic as I thought it was
master
Vexu 2020-05-14 19:56:55 +03:00
parent c4552ee8ed
commit c77fee0344
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
2 changed files with 26 additions and 12 deletions

View File

@ -213,7 +213,7 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All
.ExpectedToken = .{ .token = index, .expected_id = .Comma }, .ExpectedToken = .{ .token = index, .expected_id = .Comma },
}); });
continue; continue;
} },
} }
}; };
if (try parseAppendedDocComment(arena, it, tree, comma)) |appended_comment| if (try parseAppendedDocComment(arena, it, tree, comma)) |appended_comment|
@ -245,6 +245,7 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All
return list; return list;
} }
/// Attempts to find next container member by searching for certain tokens
fn findNextContainerMember(it: *TokenIterator) void { fn findNextContainerMember(it: *TokenIterator) void {
var level: u32 = 0; var level: u32 = 0;
while (true) { while (true) {
@ -294,27 +295,30 @@ fn findNextContainerMember(it: *TokenIterator) void {
} }
} }
/// Attempts to find `wanted` token, keeps track of parentheses. /// Attempts to find the next statement by searching for a semicolon
fn findToken(it: *TokenIterator, wanted: Token.Id) void { fn findNextStmt(it: *TokenIterator) void {
var count: u32 = 0; var level: u32 = 0;
while (true) { while (true) {
const tok = nextToken(it); const tok = nextToken(it);
switch (tok.ptr.id) { switch (tok.ptr.id) {
.LParen, .LBracket, .LBrace => count += 1, .LBrace => level += 1,
.RParen, .RBracket, .RBrace => { .RBrace => {
if (count == 0) { if (level == 0) {
putBackToken(it, tok.index); putBackToken(it, tok.index);
return; return;
} }
count -= 1; level -= 1;
},
.Semicolon => {
if (level == 0) {
return;
}
}, },
.Eof => { .Eof => {
putBackToken(it, tok.index); putBackToken(it, tok.index);
return; return;
}, },
else => { else => {},
if (tok.ptr.id == wanted and count == 0) return;
},
} }
} }
} }
@ -1186,7 +1190,7 @@ fn parseBlock(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
error.OutOfMemory => return error.OutOfMemory, error.OutOfMemory => return error.OutOfMemory,
error.ParseError => { error.ParseError => {
// try to skip to the next statement // try to skip to the next statement
findToken(it, .Semicolon); findNextStmt(it);
continue; continue;
}, },
}) orelse break; }) orelse break;

View File

@ -138,6 +138,16 @@ test "recovery: invalid container members" {
}); });
} }
test "recovery: invalid parameter" {
try testError(
\\fn main() void {
\\ a(comptime T: type)
\\}
, &[_]Error{
.ExpectedToken,
});
}
test "zig fmt: top-level fields" { test "zig fmt: top-level fields" {
try testCanonical( try testCanonical(
\\a: did_you_know, \\a: did_you_know,