| ... | ... | @@ -13,7 +13,7 @@ pub const Error = error{ParseError} || Allocator.Error; |
| 13 | 13 | |
| 14 | 14 | /// Result should be freed with tree.deinit() when there are |
| 15 | 15 | /// no more references to any of the tokens or nodes. |
| 16 | | pub fn parse(allocator: *Allocator, source: []const u8) !*Tree { |
| 16 | pub fn parse(allocator: *Allocator, source: []const u8) Allocator.Error!*Tree { |
| 17 | 17 | const tree = blk: { |
| 18 | 18 | // This block looks unnecessary, but is a "foot-shield" to prevent the SegmentedLists |
| 19 | 19 | // from being initialized with a pointer to this `arena`, which is created on |
| ... | ... | @@ -48,29 +48,32 @@ pub fn parse(allocator: *Allocator, source: []const u8) !*Tree { |
| 48 | 48 | |
| 49 | 49 | while (it.peek().?.id == .LineComment) _ = it.next(); |
| 50 | 50 | |
| 51 | | tree.root_node = try parseRoot(arena, &it, tree); |
| 51 | tree.root_node = parseRoot(arena, &it, tree) catch |err| blk: { |
| 52 | switch (err) { |
| 53 | error.ParseError => { |
| 54 | assert(tree.errors.len != 0); |
| 55 | break :blk undefined; |
| 56 | }, |
| 57 | error.OutOfMemory => { |
| 58 | return error.OutOfMemory; |
| 59 | }, |
| 60 | } |
| 61 | }; |
| 62 | |
| 52 | 63 | return tree; |
| 53 | 64 | } |
| 54 | 65 | |
| 55 | 66 | /// Root <- skip ContainerMembers eof |
| 56 | | fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error!*Node.Root { |
| 67 | fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!*Node.Root { |
| 57 | 68 | const node = try arena.create(Node.Root); |
| 58 | 69 | node.* = Node.Root{ |
| 59 | | .decls = undefined, |
| 60 | | .eof_token = undefined, |
| 61 | | }; |
| 62 | | node.decls = parseContainerMembers(arena, it, tree) catch |err| { |
| 63 | | // TODO: Switch on the error type |
| 64 | | // https://github.com/ziglang/zig/issues/2473 |
| 65 | | if (err == error.ParseError) return node; |
| 66 | | assert(err == Allocator.Error.OutOfMemory); |
| 67 | | return Allocator.Error.OutOfMemory; |
| 68 | | }; |
| 69 | | node.eof_token = eatToken(it, .Eof) orelse { |
| 70 | | try tree.errors.push(AstError{ |
| 71 | | .ExpectedContainerMembers = AstError.ExpectedContainerMembers{ .token = it.index }, |
| 72 | | }); |
| 73 | | return node; |
| 70 | .decls = try parseContainerMembers(arena, it, tree), |
| 71 | .eof_token = eatToken(it, .Eof) orelse { |
| 72 | try tree.errors.push(AstError{ |
| 73 | .ExpectedContainerMembers = .{ .token = it.index }, |
| 74 | }); |
| 75 | return error.ParseError; |
| 76 | }, |
| 74 | 77 | }; |
| 75 | 78 | return node; |
| 76 | 79 | } |
| ... | ... | @@ -303,7 +306,17 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 303 | 306 | fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 304 | 307 | const cc = parseFnCC(arena, it, tree); |
| 305 | 308 | const fn_token = eatToken(it, .Keyword_fn) orelse { |
| 306 | | if (cc == null) return null else return error.ParseError; |
| 309 | if (cc) |fnCC| { |
| 310 | if (fnCC == .Extern) { |
| 311 | putBackToken(it, fnCC.Extern); // 'extern' is also used in ContainerDecl |
| 312 | } else { |
| 313 | try tree.errors.push(AstError{ |
| 314 | .ExpectedToken = .{ .token = it.index, .expected_id = .Keyword_fn }, |
| 315 | }); |
| 316 | return error.ParseError; |
| 317 | } |
| 318 | } |
| 319 | return null; |
| 307 | 320 | }; |
| 308 | 321 | const name_token = eatToken(it, .Identifier); |
| 309 | 322 | const lparen = try expectToken(it, tree, .LParen); |
| ... | ... | @@ -390,7 +403,7 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 390 | 403 | .visib_token = null, |
| 391 | 404 | .thread_local_token = null, |
| 392 | 405 | .name_token = name_token, |
| 393 | | .eq_token = eq_token orelse undefined, |
| 406 | .eq_token = eq_token, |
| 394 | 407 | .mut_token = mut_token, |
| 395 | 408 | .comptime_token = null, |
| 396 | 409 | .extern_export_token = null, |
| ... | ... | @@ -2177,7 +2190,7 @@ fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 2177 | 2190 | node.* = Node.PrefixOp{ |
| 2178 | 2191 | .op_token = token.index, |
| 2179 | 2192 | .op = op, |
| 2180 | | .rhs = undefined, |
| 2193 | .rhs = undefined, // set by caller |
| 2181 | 2194 | }; |
| 2182 | 2195 | return &node.base; |
| 2183 | 2196 | } |
| ... | ... | @@ -2819,8 +2832,8 @@ fn parseUse(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 2819 | 2832 | .doc_comments = null, |
| 2820 | 2833 | .visib_token = null, |
| 2821 | 2834 | .use_token = token, |
| 2822 | | .expr = undefined, |
| 2823 | | .semicolon_token = undefined, |
| 2835 | .expr = undefined, // set by caller |
| 2836 | .semicolon_token = undefined, // set by caller |
| 2824 | 2837 | }; |
| 2825 | 2838 | return &node.base; |
| 2826 | 2839 | } |
| ... | ... | @@ -2979,9 +2992,9 @@ fn createInfixOp(arena: *Allocator, index: TokenIndex, op: Node.InfixOp.Op) !*No |
| 2979 | 2992 | const node = try arena.create(Node.InfixOp); |
| 2980 | 2993 | node.* = Node.InfixOp{ |
| 2981 | 2994 | .op_token = index, |
| 2982 | | .lhs = undefined, |
| 2995 | .lhs = undefined, // set by caller |
| 2983 | 2996 | .op = op, |
| 2984 | | .rhs = undefined, |
| 2997 | .rhs = undefined, // set by caller |
| 2985 | 2998 | }; |
| 2986 | 2999 | return &node.base; |
| 2987 | 3000 | } |