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) {...@@ -165,6 +165,7 @@ pub const Error = union(enum) {
165 ExpectedDerefOrUnwrap: ExpectedDerefOrUnwrap,165 ExpectedDerefOrUnwrap: ExpectedDerefOrUnwrap,
166 ExpectedSuffixOp: ExpectedSuffixOp,166 ExpectedSuffixOp: ExpectedSuffixOp,
167 DeclBetweenFields: DeclBetweenFields,167 DeclBetweenFields: DeclBetweenFields,
168 MissingComma: MissingComma,
168169
169 pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void {170 pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void {
170 switch (self.*) {171 switch (self.*) {
...@@ -213,6 +214,7 @@ pub const Error = union(enum) {...@@ -213,6 +214,7 @@ pub const Error = union(enum) {
213 .ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream),214 .ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream),
214 .ExpectedSuffixOp => |*x| return x.render(tokens, stream),215 .ExpectedSuffixOp => |*x| return x.render(tokens, stream),
215 .DeclBetweenFields => |*x| return x.render(tokens, stream),216 .DeclBetweenFields => |*x| return x.render(tokens, stream),
217 .MissingComma => |*x| return x.render(tokens, stream),
216 }218 }
217 }219 }
218220
...@@ -263,6 +265,7 @@ pub const Error = union(enum) {...@@ -263,6 +265,7 @@ pub const Error = union(enum) {
263 .ExpectedDerefOrUnwrap => |x| return x.token,265 .ExpectedDerefOrUnwrap => |x| return x.token,
264 .ExpectedSuffixOp => |x| return x.token,266 .ExpectedSuffixOp => |x| return x.token,
265 .DeclBetweenFields => |x| return x.token,267 .DeclBetweenFields => |x| return x.token,
268 .MissingComma => |x| return x.token,
266 }269 }
267 }270 }
268271
...@@ -308,6 +311,7 @@ pub const Error = union(enum) {...@@ -308,6 +311,7 @@ pub const Error = union(enum) {
308 pub const ExtraVolatileQualifier = SimpleError("Extra volatile qualifier");311 pub const ExtraVolatileQualifier = SimpleError("Extra volatile qualifier");
309 pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier");312 pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier");
310 pub const DeclBetweenFields = SimpleError("Declarations are not allowed between container fields");313 pub const DeclBetweenFields = SimpleError("Declarations are not allowed between container fields");
314 pub const MissingComma = SimpleError("Expected comma between items");
311315
312 pub const ExpectedCall = struct {316 pub const ExpectedCall = struct {
313 node: *Node,317 node: *Node,
lib/std/zig/parse.zig+26-2
...@@ -1083,7 +1083,14 @@ fn parseBlock(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1083,7 +1083,14 @@ fn parseBlock(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
10831083
1084 var statements = Node.Block.StatementList.init(arena);1084 var statements = Node.Block.StatementList.init(arena);
1085 while (true) {1085 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;
1087 try statements.push(statement);1094 try statements.push(statement);
1088 }1095 }
10891096
...@@ -2816,7 +2823,24 @@ fn ListParseFn(comptime L: type, comptime nodeParseFn: var) ParseFn(L) {...@@ -2816,7 +2823,24 @@ fn ListParseFn(comptime L: type, comptime nodeParseFn: var) ParseFn(L) {
2816 var list = L.init(arena);2823 var list = L.init(arena);
2817 while (try nodeParseFn(arena, it, tree)) |node| {2824 while (try nodeParseFn(arena, it, tree)) |node| {
2818 try list.push(node);2825 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 }
2820 }2844 }
2821 return list;2845 return list;
2822 }2846 }
lib/std/zig/parser_test.zig+24
...@@ -6,6 +6,30 @@ test "zig fmt: fault tolerant parsing" {...@@ -6,6 +6,30 @@ test "zig fmt: fault tolerant parsing" {
6 .ExpectedInlinable,6 .ExpectedInlinable,
7 .ExpectedInlinable,7 .ExpectedInlinable,
8 });8 });
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 });
9}33}
1034
11test "zig fmt: top-level fields" {35test "zig fmt: top-level fields" {