| ... | @@ -10,6 +10,13 @@ const Token = std.zig.Token; | ... | @@ -10,6 +10,13 @@ const Token = std.zig.Token; |
| 10 | | 10 | |
| 11 | pub const Error = error{ParseError} || Allocator.Error; | 11 | pub const Error = error{ParseError} || Allocator.Error; |
| 12 | | 12 | |
| | 13 | /// This is the maximum length of a list that will be copied into the ast.Tree |
| | 14 | /// arena when parsing. If the list is longer than this, the ast.Tree will have |
| | 15 | /// a reference to the memory allocated in the general purpose allocator, and |
| | 16 | /// will free it separately. Simply put, lists longer than this will elide the |
| | 17 | /// memcpy(). |
| | 18 | const large_list_len = 512; |
| | 19 | |
| 13 | /// Result should be freed with tree.deinit() when there are | 20 | /// Result should be freed with tree.deinit() when there are |
| 14 | /// no more references to any of the tokens or nodes. | 21 | /// no more references to any of the tokens or nodes. |
| 15 | pub fn parse(gpa: *Allocator, source: []const u8) Allocator.Error!*Tree { | 22 | pub fn parse(gpa: *Allocator, source: []const u8) Allocator.Error!*Tree { |
| ... | @@ -32,6 +39,11 @@ pub fn parse(gpa: *Allocator, source: []const u8) Allocator.Error!*Tree { | ... | @@ -32,6 +39,11 @@ pub fn parse(gpa: *Allocator, source: []const u8) Allocator.Error!*Tree { |
| 32 | .tokens = tokens.items, | 39 | .tokens = tokens.items, |
| 33 | .errors = .{}, | 40 | .errors = .{}, |
| 34 | .tok_i = 0, | 41 | .tok_i = 0, |
| | 42 | .owned_memory = .{}, |
| | 43 | }; |
| | 44 | defer parser.owned_memory.deinit(gpa); |
| | 45 | errdefer for (parser.owned_memory.items) |list| { |
| | 46 | gpa.free(list); |
| 35 | }; | 47 | }; |
| 36 | defer parser.errors.deinit(gpa); | 48 | defer parser.errors.deinit(gpa); |
| 37 | errdefer parser.arena.deinit(); | 49 | errdefer parser.arena.deinit(); |
| ... | @@ -46,6 +58,7 @@ pub fn parse(gpa: *Allocator, source: []const u8) Allocator.Error!*Tree { | ... | @@ -46,6 +58,7 @@ pub fn parse(gpa: *Allocator, source: []const u8) Allocator.Error!*Tree { |
| 46 | .source = source, | 58 | .source = source, |
| 47 | .tokens = tokens.toOwnedSlice(), | 59 | .tokens = tokens.toOwnedSlice(), |
| 48 | .errors = parser.errors.toOwnedSlice(gpa), | 60 | .errors = parser.errors.toOwnedSlice(gpa), |
| | 61 | .owned_memory = parser.owned_memory.toOwnedSlice(gpa), |
| 49 | .root_node = root_node, | 62 | .root_node = root_node, |
| 50 | .arena = parser.arena.state, | 63 | .arena = parser.arena.state, |
| 51 | }; | 64 | }; |
| ... | @@ -60,6 +73,7 @@ const Parser = struct { | ... | @@ -60,6 +73,7 @@ const Parser = struct { |
| 60 | tokens: []const Token, | 73 | tokens: []const Token, |
| 61 | tok_i: TokenIndex, | 74 | tok_i: TokenIndex, |
| 62 | errors: std.ArrayListUnmanaged(AstError), | 75 | errors: std.ArrayListUnmanaged(AstError), |
| | 76 | owned_memory: std.ArrayListUnmanaged([]u8), |
| 63 | | 77 | |
| 64 | /// Root <- skip ContainerMembers eof | 78 | /// Root <- skip ContainerMembers eof |
| 65 | fn parseRoot(p: *Parser) Allocator.Error!*Node.Root { | 79 | fn parseRoot(p: *Parser) Allocator.Error!*Node.Root { |
| ... | @@ -1307,11 +1321,19 @@ const Parser = struct { | ... | @@ -1307,11 +1321,19 @@ const Parser = struct { |
| 1307 | const next = (try p.parseFieldInit()) orelse break; | 1321 | const next = (try p.parseFieldInit()) orelse break; |
| 1308 | try init_list.append(next); | 1322 | try init_list.append(next); |
| 1309 | } | 1323 | } |
| | 1324 | |
| | 1325 | const list = if (init_list.items.len > large_list_len) blk: { |
| | 1326 | try p.owned_memory.ensureCapacity(p.gpa, p.owned_memory.items.len + 1); |
| | 1327 | const list = init_list.toOwnedSlice(); |
| | 1328 | p.owned_memory.appendAssumeCapacity(std.mem.sliceAsBytes(list)); |
| | 1329 | break :blk list; |
| | 1330 | } else try p.arena.allocator.dupe(*Node, init_list.items); |
| | 1331 | |
| 1310 | const node = try p.arena.allocator.create(Node.StructInitializer); | 1332 | const node = try p.arena.allocator.create(Node.StructInitializer); |
| 1311 | node.* = .{ | 1333 | node.* = .{ |
| 1312 | .lhs = lhs, | 1334 | .lhs = lhs, |
| 1313 | .rtoken = try p.expectToken(.RBrace), | 1335 | .rtoken = try p.expectToken(.RBrace), |
| 1314 | .list = try p.arena.allocator.dupe(*Node, init_list.items), | 1336 | .list = list, |
| 1315 | }; | 1337 | }; |
| 1316 | return &node.base; | 1338 | return &node.base; |
| 1317 | } | 1339 | } |
| ... | @@ -1322,11 +1344,19 @@ const Parser = struct { | ... | @@ -1322,11 +1344,19 @@ const Parser = struct { |
| 1322 | const next = (try p.parseExpr()) orelse break; | 1344 | const next = (try p.parseExpr()) orelse break; |
| 1323 | try init_list.append(next); | 1345 | try init_list.append(next); |
| 1324 | } | 1346 | } |
| | 1347 | |
| | 1348 | const list = if (init_list.items.len > large_list_len) blk: { |
| | 1349 | try p.owned_memory.ensureCapacity(p.gpa, p.owned_memory.items.len + 1); |
| | 1350 | const list = init_list.toOwnedSlice(); |
| | 1351 | p.owned_memory.appendAssumeCapacity(std.mem.sliceAsBytes(list)); |
| | 1352 | break :blk list; |
| | 1353 | } else try p.arena.allocator.dupe(*Node, init_list.items); |
| | 1354 | |
| 1325 | const node = try p.arena.allocator.create(Node.ArrayInitializer); | 1355 | const node = try p.arena.allocator.create(Node.ArrayInitializer); |
| 1326 | node.* = .{ | 1356 | node.* = .{ |
| 1327 | .lhs = lhs, | 1357 | .lhs = lhs, |
| 1328 | .rtoken = try p.expectToken(.RBrace), | 1358 | .rtoken = try p.expectToken(.RBrace), |
| 1329 | .list = try p.arena.allocator.dupe(*Node, init_list.items), | 1359 | .list = list, |
| 1330 | }; | 1360 | }; |
| 1331 | return &node.base; | 1361 | return &node.base; |
| 1332 | } | 1362 | } |
| ... | @@ -1355,11 +1385,19 @@ const Parser = struct { | ... | @@ -1355,11 +1385,19 @@ const Parser = struct { |
| 1355 | const next = (try p.parseFieldInit()) orelse break; | 1385 | const next = (try p.parseFieldInit()) orelse break; |
| 1356 | try init_list.append(next); | 1386 | try init_list.append(next); |
| 1357 | } | 1387 | } |
| | 1388 | |
| | 1389 | const list = if (init_list.items.len > large_list_len) blk: { |
| | 1390 | try p.owned_memory.ensureCapacity(p.gpa, p.owned_memory.items.len + 1); |
| | 1391 | const list = init_list.toOwnedSlice(); |
| | 1392 | p.owned_memory.appendAssumeCapacity(std.mem.sliceAsBytes(list)); |
| | 1393 | break :blk list; |
| | 1394 | } else try p.arena.allocator.dupe(*Node, init_list.items); |
| | 1395 | |
| 1358 | const node = try p.arena.allocator.create(Node.StructInitializerDot); | 1396 | const node = try p.arena.allocator.create(Node.StructInitializerDot); |
| 1359 | node.* = .{ | 1397 | node.* = .{ |
| 1360 | .dot = dot, | 1398 | .dot = dot, |
| 1361 | .rtoken = try p.expectToken(.RBrace), | 1399 | .rtoken = try p.expectToken(.RBrace), |
| 1362 | .list = try p.arena.allocator.dupe(*Node, init_list.items), | 1400 | .list = list, |
| 1363 | }; | 1401 | }; |
| 1364 | return &node.base; | 1402 | return &node.base; |
| 1365 | } | 1403 | } |
| ... | @@ -1370,11 +1408,19 @@ const Parser = struct { | ... | @@ -1370,11 +1408,19 @@ const Parser = struct { |
| 1370 | const next = (try p.parseExpr()) orelse break; | 1408 | const next = (try p.parseExpr()) orelse break; |
| 1371 | try init_list.append(next); | 1409 | try init_list.append(next); |
| 1372 | } | 1410 | } |
| | 1411 | |
| | 1412 | const list = if (init_list.items.len > large_list_len) blk: { |
| | 1413 | try p.owned_memory.ensureCapacity(p.gpa, p.owned_memory.items.len + 1); |
| | 1414 | const list = init_list.toOwnedSlice(); |
| | 1415 | p.owned_memory.appendAssumeCapacity(std.mem.sliceAsBytes(list)); |
| | 1416 | break :blk list; |
| | 1417 | } else try p.arena.allocator.dupe(*Node, init_list.items); |
| | 1418 | |
| 1373 | const node = try p.arena.allocator.create(Node.ArrayInitializerDot); | 1419 | const node = try p.arena.allocator.create(Node.ArrayInitializerDot); |
| 1374 | node.* = .{ | 1420 | node.* = .{ |
| 1375 | .dot = dot, | 1421 | .dot = dot, |
| 1376 | .rtoken = try p.expectToken(.RBrace), | 1422 | .rtoken = try p.expectToken(.RBrace), |
| 1377 | .list = try p.arena.allocator.dupe(*Node, init_list.items), | 1423 | .list = list, |
| 1378 | }; | 1424 | }; |
| 1379 | return &node.base; | 1425 | return &node.base; |
| 1380 | } | 1426 | } |