authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-05-13 17:21:27+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-05-13 17:21:27+03:00
logbe392777b763028a02866342b12915a1e69ebdf1
tree4282ef39d369811480bf2d74e9fef6a434d9f68c
parent91358f3092fb2004bb46572d44a0e377ed400565
signature Commit is signed but in an unrecognized format.

continue parsing after missing commas and invalid statements


3 files changed, 54 insertions(+), 2 deletions(-)

lib/std/zig/ast.zig+4
......@@ -165,6 +165,7 @@ pub const Error = union(enum) {
165165 ExpectedDerefOrUnwrap: ExpectedDerefOrUnwrap,
166166 ExpectedSuffixOp: ExpectedSuffixOp,
167167 DeclBetweenFields: DeclBetweenFields,
168 MissingComma: MissingComma,
168169
169170 pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void {
170171 switch (self.*) {
......@@ -213,6 +214,7 @@ pub const Error = union(enum) {
213214 .ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream),
214215 .ExpectedSuffixOp => |*x| return x.render(tokens, stream),
215216 .DeclBetweenFields => |*x| return x.render(tokens, stream),
217 .MissingComma => |*x| return x.render(tokens, stream),
216218 }
217219 }
218220
......@@ -263,6 +265,7 @@ pub const Error = union(enum) {
263265 .ExpectedDerefOrUnwrap => |x| return x.token,
264266 .ExpectedSuffixOp => |x| return x.token,
265267 .DeclBetweenFields => |x| return x.token,
268 .MissingComma => |x| return x.token,
266269 }
267270 }
268271
......@@ -308,6 +311,7 @@ pub const Error = union(enum) {
308311 pub const ExtraVolatileQualifier = SimpleError("Extra volatile qualifier");
309312 pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier");
310313 pub const DeclBetweenFields = SimpleError("Declarations are not allowed between container fields");
314 pub const MissingComma = SimpleError("Expected comma between items");
311315
312316 pub const ExpectedCall = struct {
313317 node: *Node,
lib/std/zig/parse.zig+26-2
......@@ -1083,7 +1083,14 @@ fn parseBlock(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
10831083
10841084 var statements = Node.Block.StatementList.init(arena);
10851085 while (true) {
1086 const statement = (try parseStatement(arena, it, tree)) orelse break;
1086 const statement = (parseStatement(arena, it, tree) catch |err| switch (err) {
1087 error.OutOfMemory => return error.OutOfMemory,
1088 error.ParseError => {
1089 // try to skip to the next statement
1090 findToken(it, .Semicolon);
1091 continue;
1092 },
1093 }) orelse break;
10871094 try statements.push(statement);
10881095 }
10891096
......@@ -2816,7 +2823,24 @@ fn ListParseFn(comptime L: type, comptime nodeParseFn: var) ParseFn(L) {
28162823 var list = L.init(arena);
28172824 while (try nodeParseFn(arena, it, tree)) |node| {
28182825 try list.push(node);
2819 if (eatToken(it, .Comma) == null) break;
2826
2827 const token = nextToken(it);
2828 switch (token.ptr.id) {
2829 .Comma => {},
2830 // all possible delimiters
2831 .Colon, .RParen, .RBrace, .RBracket => {
2832 putBackToken(it, token.index);
2833 break;
2834 },
2835 else => {
2836 // this is likely just a missing comma,
2837 // continue parsing this list and give an error
2838 try tree.errors.push(.{
2839 .MissingComma = .{ .token = token.index },
2840 });
2841 putBackToken(it, token.index);
2842 },
2843 }
28202844 }
28212845 return list;
28222846 }
lib/std/zig/parser_test.zig+24
......@@ -6,6 +6,30 @@ test "zig fmt: fault tolerant parsing" {
66 .ExpectedInlinable,
77 .ExpectedInlinable,
88 });
9 try testError(
10 \\test "" {
11 \\ foo + +;
12 \\ inline;
13 \\}
14 , &[_]Error{
15 .InvalidToken,
16 .ExpectedInlinable,
17 });
18 try testError(
19 \\test "" {
20 \\ switch (foo) {
21 \\ 2 => {}
22 \\ 3 => {}
23 \\ else => {
24 \\ inline;
25 \\ }
26 \\ }
27 \\}
28 , &[_]Error{
29 .MissingComma,
30 .MissingComma,
31 .ExpectedInlinable,
32 });
933}
1034
1135test "zig fmt: top-level fields" {