diff options
| author | Vexu <git@vexu.eu> | 2020-05-13 17:21:27 +0300 |
|---|---|---|
| committer | Vexu <git@vexu.eu> | 2020-05-13 17:21:27 +0300 |
| commit | be392777b763028a02866342b12915a1e69ebdf1 (patch) | |
| tree | 4282ef39d369811480bf2d74e9fef6a434d9f68c /lib/std | |
| parent | 91358f3092fb2004bb46572d44a0e377ed400565 (diff) | |
| download | zig-be392777b763028a02866342b12915a1e69ebdf1.tar.gz zig-be392777b763028a02866342b12915a1e69ebdf1.zip | |
continue parsing after missing commas and invalid statements
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/zig/ast.zig | 4 | ||||
| -rw-r--r-- | lib/std/zig/parse.zig | 28 | ||||
| -rw-r--r-- | lib/std/zig/parser_test.zig | 24 |
3 files changed, 54 insertions, 2 deletions
diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 8dec2de15c..dd9abe61ac 100644 --- a/lib/std/zig/ast.zig +++ b/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, diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 586af02194..ad4f5e1242 100644 --- a/lib/std/zig/parse.zig +++ b/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; } diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index a925aacc0b..2c8b53f7f0 100644 --- a/lib/std/zig/parser_test.zig +++ b/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" { |
