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