| ... | ... | @@ -57,16 +57,10 @@ pub fn parse(allocator: *Allocator, source: []const u8) Allocator.Error!*Tree { |
| 57 | 57 | fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error!*Node.Root { |
| 58 | 58 | const node = try arena.create(Node.Root); |
| 59 | 59 | node.* = .{ |
| 60 | | .decls = try parseContainerMembers(arena, it, tree), |
| 61 | | .eof_token = eatToken(it, .Eof) orelse blk: { |
| 62 | | // parseContainerMembers will try to skip as much |
| 63 | | // invalid tokens as it can so this can only be a '}' |
| 64 | | const tok = eatToken(it, .RBrace).?; |
| 65 | | try tree.errors.push(.{ |
| 66 | | .ExpectedContainerMembers = .{ .token = tok }, |
| 67 | | }); |
| 68 | | break :blk tok; |
| 69 | | }, |
| 60 | .decls = try parseContainerMembers(arena, it, tree, true), |
| 61 | // parseContainerMembers will try to skip as much |
| 62 | // invalid tokens as it can so this can only be the EOF |
| 63 | .eof_token = eatToken(it, .Eof).?, |
| 70 | 64 | }; |
| 71 | 65 | return node; |
| 72 | 66 | } |
| ... | ... | @@ -78,7 +72,7 @@ fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error |
| 78 | 72 | /// / KEYWORD_pub? ContainerField COMMA ContainerMembers |
| 79 | 73 | /// / KEYWORD_pub? ContainerField |
| 80 | 74 | /// / |
| 81 | | fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !Node.Root.DeclList { |
| 75 | fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree, top_level: bool) !Node.Root.DeclList { |
| 82 | 76 | var list = Node.Root.DeclList.init(arena); |
| 83 | 77 | |
| 84 | 78 | var field_state: union(enum) { |
| ... | ... | @@ -205,9 +199,15 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No |
| 205 | 199 | // try to continue parsing |
| 206 | 200 | const index = it.index; |
| 207 | 201 | findNextContainerMember(it); |
| 208 | | switch (it.peek().?.id) { |
| 209 | | .Eof, .RBrace => break, |
| 202 | const next = it.peek().?.id; |
| 203 | switch (next) { |
| 204 | .Eof => break, |
| 210 | 205 | else => { |
| 206 | if (next == .RBrace) { |
| 207 | if (!top_level) break; |
| 208 | _ = nextToken(it); |
| 209 | } |
| 210 | |
| 211 | 211 | // add error and continue |
| 212 | 212 | try tree.errors.push(.{ |
| 213 | 213 | .ExpectedToken = .{ .token = index, .expected_id = .Comma }, |
| ... | ... | @@ -228,9 +228,15 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No |
| 228 | 228 | }); |
| 229 | 229 | } |
| 230 | 230 | |
| 231 | | switch (it.peek().?.id) { |
| 232 | | .Eof, .RBrace => break, |
| 231 | const next = it.peek().?.id; |
| 232 | switch (next) { |
| 233 | .Eof => break, |
| 233 | 234 | else => { |
| 235 | if (next == .RBrace) { |
| 236 | if (!top_level) break; |
| 237 | _ = nextToken(it); |
| 238 | } |
| 239 | |
| 234 | 240 | // this was likely not supposed to end yet, |
| 235 | 241 | // try to find the next declaration |
| 236 | 242 | const index = it.index; |
| ... | ... | @@ -2778,7 +2784,7 @@ fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 2778 | 2784 | fn parseContainerDeclAuto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 2779 | 2785 | const node = (try parseContainerDeclType(arena, it, tree)) orelse return null; |
| 2780 | 2786 | const lbrace = try expectToken(it, tree, .LBrace); |
| 2781 | | const members = try parseContainerMembers(arena, it, tree); |
| 2787 | const members = try parseContainerMembers(arena, it, tree, false); |
| 2782 | 2788 | const rbrace = try expectToken(it, tree, .RBrace); |
| 2783 | 2789 | |
| 2784 | 2790 | const decl_type = node.cast(Node.ContainerDecl).?; |