authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-05-14 19:56:55+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-05-14 19:56:55+03:00
logc77fee03448817366a2cda98915bc31ba8f2b451
tree01adc52f94627b21c6f212f8a0babd8de7dea63e
parentc4552ee8edec961defb161e1b828a818f8d407bb
signature Commit is signed but in an unrecognized format.

fix infinite loop

findToken wasn't as generic as I thought it was

2 files changed, 26 insertions(+), 12 deletions(-)

lib/std/zig/parse.zig+16-12
......@@ -213,7 +213,7 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All
213213 .ExpectedToken = .{ .token = index, .expected_id = .Comma },
214214 });
215215 continue;
216 }
216 },
217217 }
218218 };
219219 if (try parseAppendedDocComment(arena, it, tree, comma)) |appended_comment|
......@@ -245,6 +245,7 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All
245245 return list;
246246}
247247
248/// Attempts to find next container member by searching for certain tokens
248249fn findNextContainerMember(it: *TokenIterator) void {
249250 var level: u32 = 0;
250251 while (true) {
......@@ -294,27 +295,30 @@ fn findNextContainerMember(it: *TokenIterator) void {
294295 }
295296}
296297
297/// Attempts to find `wanted` token, keeps track of parentheses.
298fn findToken(it: *TokenIterator, wanted: Token.Id) void {
299 var count: u32 = 0;
298/// Attempts to find the next statement by searching for a semicolon
299fn findNextStmt(it: *TokenIterator) void {
300 var level: u32 = 0;
300301 while (true) {
301302 const tok = nextToken(it);
302303 switch (tok.ptr.id) {
303 .LParen, .LBracket, .LBrace => count += 1,
304 .RParen, .RBracket, .RBrace => {
305 if (count == 0) {
304 .LBrace => level += 1,
305 .RBrace => {
306 if (level == 0) {
306307 putBackToken(it, tok.index);
307308 return;
308309 }
309 count -= 1;
310 level -= 1;
311 },
312 .Semicolon => {
313 if (level == 0) {
314 return;
315 }
310316 },
311317 .Eof => {
312318 putBackToken(it, tok.index);
313319 return;
314320 },
315 else => {
316 if (tok.ptr.id == wanted and count == 0) return;
317 },
321 else => {},
318322 }
319323 }
320324}
......@@ -1186,7 +1190,7 @@ fn parseBlock(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11861190 error.OutOfMemory => return error.OutOfMemory,
11871191 error.ParseError => {
11881192 // try to skip to the next statement
1189 findToken(it, .Semicolon);
1193 findNextStmt(it);
11901194 continue;
11911195 },
11921196 }) orelse break;
lib/std/zig/parser_test.zig+10
......@@ -138,6 +138,16 @@ test "recovery: invalid container members" {
138138 });
139139}
140140
141test "recovery: invalid parameter" {
142 try testError(
143 \\fn main() void {
144 \\ a(comptime T: type)
145 \\}
146 , &[_]Error{
147 .ExpectedToken,
148 });
149}
150
141151test "zig fmt: top-level fields" {
142152 try testCanonical(
143153 \\a: did_you_know,