| ... | ... | @@ -4,6 +4,16 @@ |
| 4 | 4 | //! For Zon syntax, the root node is at nodes[0] and contains lhs as the node |
| 5 | 5 | //! index of the main expression. |
| 6 | 6 | |
| 7 | const std = @import("../std.zig"); |
| 8 | const assert = std.debug.assert; |
| 9 | const testing = std.testing; |
| 10 | const mem = std.mem; |
| 11 | const Token = std.zig.Token; |
| 12 | const Ast = @This(); |
| 13 | const Allocator = std.mem.Allocator; |
| 14 | const Parse = @import("Parse.zig"); |
| 15 | const Writer = std.Io.Writer; |
| 16 | |
| 7 | 17 | /// Reference to externally-owned data. |
| 8 | 18 | source: [:0]const u8, |
| 9 | 19 | |
| ... | ... | @@ -128,12 +138,6 @@ pub fn deinit(tree: *Ast, gpa: Allocator) void { |
| 128 | 138 | tree.* = undefined; |
| 129 | 139 | } |
| 130 | 140 | |
| 131 | | pub const RenderError = error{ |
| 132 | | /// Ran out of memory allocating call stack frames to complete rendering, or |
| 133 | | /// ran out of memory allocating space in the output buffer. |
| 134 | | OutOfMemory, |
| 135 | | }; |
| 136 | | |
| 137 | 141 | pub const Mode = enum { zig, zon }; |
| 138 | 142 | |
| 139 | 143 | /// Result should be freed with tree.deinit() when there are |
| ... | ... | @@ -199,27 +203,25 @@ pub fn parse(gpa: Allocator, source: [:0]const u8, mode: Mode) Allocator.Error!A |
| 199 | 203 | |
| 200 | 204 | /// `gpa` is used for allocating the resulting formatted source code. |
| 201 | 205 | /// Caller owns the returned slice of bytes, allocated with `gpa`. |
| 202 | | pub fn render(tree: Ast, gpa: Allocator) RenderError![]u8 { |
| 203 | | var buffer = std.ArrayList(u8).init(gpa); |
| 204 | | defer buffer.deinit(); |
| 205 | | |
| 206 | | try tree.renderToArrayList(&buffer, .{}); |
| 207 | | return buffer.toOwnedSlice(); |
| 206 | pub fn renderAlloc(tree: Ast, gpa: Allocator) error{OutOfMemory}![]u8 { |
| 207 | var aw: std.io.Writer.Allocating = .init(gpa); |
| 208 | defer aw.deinit(); |
| 209 | render(tree, gpa, &aw.writer, .{}) catch |err| switch (err) { |
| 210 | error.WriteFailed => return error.OutOfMemory, |
| 211 | }; |
| 212 | return aw.toOwnedSlice(); |
| 208 | 213 | } |
| 209 | 214 | |
| 210 | | pub const Fixups = private_render.Fixups; |
| 215 | pub const Render = @import("Ast/Render.zig"); |
| 211 | 216 | |
| 212 | | pub fn renderToArrayList(tree: Ast, buffer: *std.ArrayList(u8), fixups: Fixups) RenderError!void { |
| 213 | | return @import("./render.zig").renderTree(buffer, tree, fixups); |
| 217 | pub fn render(tree: Ast, gpa: Allocator, w: *Writer, fixups: Render.Fixups) Render.Error!void { |
| 218 | return Render.tree(gpa, w, tree, fixups); |
| 214 | 219 | } |
| 215 | 220 | |
| 216 | 221 | /// Returns an extra offset for column and byte offset of errors that |
| 217 | 222 | /// should point after the token in the error message. |
| 218 | 223 | pub fn errorOffset(tree: Ast, parse_error: Error) u32 { |
| 219 | | return if (parse_error.token_is_prev) |
| 220 | | @as(u32, @intCast(tree.tokenSlice(parse_error.token).len)) |
| 221 | | else |
| 222 | | 0; |
| 224 | return if (parse_error.token_is_prev) @intCast(tree.tokenSlice(parse_error.token).len) else 0; |
| 223 | 225 | } |
| 224 | 226 | |
| 225 | 227 | pub fn tokenLocation(self: Ast, start_offset: ByteOffset, token_index: TokenIndex) Location { |
| ... | ... | @@ -318,254 +320,254 @@ pub fn rootDecls(tree: Ast) []const Node.Index { |
| 318 | 320 | } |
| 319 | 321 | } |
| 320 | 322 | |
| 321 | | pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void { |
| 323 | pub fn renderError(tree: Ast, parse_error: Error, w: *Writer) Writer.Error!void { |
| 322 | 324 | switch (parse_error.tag) { |
| 323 | 325 | .asterisk_after_ptr_deref => { |
| 324 | 326 | // Note that the token will point at the `.*` but ideally the source |
| 325 | 327 | // location would point to the `*` after the `.*`. |
| 326 | | return stream.writeAll("'.*' cannot be followed by '*'; are you missing a space?"); |
| 328 | return w.writeAll("'.*' cannot be followed by '*'; are you missing a space?"); |
| 327 | 329 | }, |
| 328 | 330 | .chained_comparison_operators => { |
| 329 | | return stream.writeAll("comparison operators cannot be chained"); |
| 331 | return w.writeAll("comparison operators cannot be chained"); |
| 330 | 332 | }, |
| 331 | 333 | .decl_between_fields => { |
| 332 | | return stream.writeAll("declarations are not allowed between container fields"); |
| 334 | return w.writeAll("declarations are not allowed between container fields"); |
| 333 | 335 | }, |
| 334 | 336 | .expected_block => { |
| 335 | | return stream.print("expected block, found '{s}'", .{ |
| 337 | return w.print("expected block, found '{s}'", .{ |
| 336 | 338 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 337 | 339 | }); |
| 338 | 340 | }, |
| 339 | 341 | .expected_block_or_assignment => { |
| 340 | | return stream.print("expected block or assignment, found '{s}'", .{ |
| 342 | return w.print("expected block or assignment, found '{s}'", .{ |
| 341 | 343 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 342 | 344 | }); |
| 343 | 345 | }, |
| 344 | 346 | .expected_block_or_expr => { |
| 345 | | return stream.print("expected block or expression, found '{s}'", .{ |
| 347 | return w.print("expected block or expression, found '{s}'", .{ |
| 346 | 348 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 347 | 349 | }); |
| 348 | 350 | }, |
| 349 | 351 | .expected_block_or_field => { |
| 350 | | return stream.print("expected block or field, found '{s}'", .{ |
| 352 | return w.print("expected block or field, found '{s}'", .{ |
| 351 | 353 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 352 | 354 | }); |
| 353 | 355 | }, |
| 354 | 356 | .expected_container_members => { |
| 355 | | return stream.print("expected test, comptime, var decl, or container field, found '{s}'", .{ |
| 357 | return w.print("expected test, comptime, var decl, or container field, found '{s}'", .{ |
| 356 | 358 | tree.tokenTag(parse_error.token).symbol(), |
| 357 | 359 | }); |
| 358 | 360 | }, |
| 359 | 361 | .expected_expr => { |
| 360 | | return stream.print("expected expression, found '{s}'", .{ |
| 362 | return w.print("expected expression, found '{s}'", .{ |
| 361 | 363 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 362 | 364 | }); |
| 363 | 365 | }, |
| 364 | 366 | .expected_expr_or_assignment => { |
| 365 | | return stream.print("expected expression or assignment, found '{s}'", .{ |
| 367 | return w.print("expected expression or assignment, found '{s}'", .{ |
| 366 | 368 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 367 | 369 | }); |
| 368 | 370 | }, |
| 369 | 371 | .expected_expr_or_var_decl => { |
| 370 | | return stream.print("expected expression or var decl, found '{s}'", .{ |
| 372 | return w.print("expected expression or var decl, found '{s}'", .{ |
| 371 | 373 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 372 | 374 | }); |
| 373 | 375 | }, |
| 374 | 376 | .expected_fn => { |
| 375 | | return stream.print("expected function, found '{s}'", .{ |
| 377 | return w.print("expected function, found '{s}'", .{ |
| 376 | 378 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 377 | 379 | }); |
| 378 | 380 | }, |
| 379 | 381 | .expected_inlinable => { |
| 380 | | return stream.print("expected 'while' or 'for', found '{s}'", .{ |
| 382 | return w.print("expected 'while' or 'for', found '{s}'", .{ |
| 381 | 383 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 382 | 384 | }); |
| 383 | 385 | }, |
| 384 | 386 | .expected_labelable => { |
| 385 | | return stream.print("expected 'while', 'for', 'inline', or '{{', found '{s}'", .{ |
| 387 | return w.print("expected 'while', 'for', 'inline', or '{{', found '{s}'", .{ |
| 386 | 388 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 387 | 389 | }); |
| 388 | 390 | }, |
| 389 | 391 | .expected_param_list => { |
| 390 | | return stream.print("expected parameter list, found '{s}'", .{ |
| 392 | return w.print("expected parameter list, found '{s}'", .{ |
| 391 | 393 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 392 | 394 | }); |
| 393 | 395 | }, |
| 394 | 396 | .expected_prefix_expr => { |
| 395 | | return stream.print("expected prefix expression, found '{s}'", .{ |
| 397 | return w.print("expected prefix expression, found '{s}'", .{ |
| 396 | 398 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 397 | 399 | }); |
| 398 | 400 | }, |
| 399 | 401 | .expected_primary_type_expr => { |
| 400 | | return stream.print("expected primary type expression, found '{s}'", .{ |
| 402 | return w.print("expected primary type expression, found '{s}'", .{ |
| 401 | 403 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 402 | 404 | }); |
| 403 | 405 | }, |
| 404 | 406 | .expected_pub_item => { |
| 405 | | return stream.writeAll("expected function or variable declaration after pub"); |
| 407 | return w.writeAll("expected function or variable declaration after pub"); |
| 406 | 408 | }, |
| 407 | 409 | .expected_return_type => { |
| 408 | | return stream.print("expected return type expression, found '{s}'", .{ |
| 410 | return w.print("expected return type expression, found '{s}'", .{ |
| 409 | 411 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 410 | 412 | }); |
| 411 | 413 | }, |
| 412 | 414 | .expected_semi_or_else => { |
| 413 | | return stream.writeAll("expected ';' or 'else' after statement"); |
| 415 | return w.writeAll("expected ';' or 'else' after statement"); |
| 414 | 416 | }, |
| 415 | 417 | .expected_semi_or_lbrace => { |
| 416 | | return stream.writeAll("expected ';' or block after function prototype"); |
| 418 | return w.writeAll("expected ';' or block after function prototype"); |
| 417 | 419 | }, |
| 418 | 420 | .expected_statement => { |
| 419 | | return stream.print("expected statement, found '{s}'", .{ |
| 421 | return w.print("expected statement, found '{s}'", .{ |
| 420 | 422 | tree.tokenTag(parse_error.token).symbol(), |
| 421 | 423 | }); |
| 422 | 424 | }, |
| 423 | 425 | .expected_suffix_op => { |
| 424 | | return stream.print("expected pointer dereference, optional unwrap, or field access, found '{s}'", .{ |
| 426 | return w.print("expected pointer dereference, optional unwrap, or field access, found '{s}'", .{ |
| 425 | 427 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 426 | 428 | }); |
| 427 | 429 | }, |
| 428 | 430 | .expected_type_expr => { |
| 429 | | return stream.print("expected type expression, found '{s}'", .{ |
| 431 | return w.print("expected type expression, found '{s}'", .{ |
| 430 | 432 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 431 | 433 | }); |
| 432 | 434 | }, |
| 433 | 435 | .expected_var_decl => { |
| 434 | | return stream.print("expected variable declaration, found '{s}'", .{ |
| 436 | return w.print("expected variable declaration, found '{s}'", .{ |
| 435 | 437 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 436 | 438 | }); |
| 437 | 439 | }, |
| 438 | 440 | .expected_var_decl_or_fn => { |
| 439 | | return stream.print("expected variable declaration or function, found '{s}'", .{ |
| 441 | return w.print("expected variable declaration or function, found '{s}'", .{ |
| 440 | 442 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 441 | 443 | }); |
| 442 | 444 | }, |
| 443 | 445 | .expected_loop_payload => { |
| 444 | | return stream.print("expected loop payload, found '{s}'", .{ |
| 446 | return w.print("expected loop payload, found '{s}'", .{ |
| 445 | 447 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 446 | 448 | }); |
| 447 | 449 | }, |
| 448 | 450 | .expected_container => { |
| 449 | | return stream.print("expected a struct, enum or union, found '{s}'", .{ |
| 451 | return w.print("expected a struct, enum or union, found '{s}'", .{ |
| 450 | 452 | tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(), |
| 451 | 453 | }); |
| 452 | 454 | }, |
| 453 | 455 | .extern_fn_body => { |
| 454 | | return stream.writeAll("extern functions have no body"); |
| 456 | return w.writeAll("extern functions have no body"); |
| 455 | 457 | }, |
| 456 | 458 | .extra_addrspace_qualifier => { |
| 457 | | return stream.writeAll("extra addrspace qualifier"); |
| 459 | return w.writeAll("extra addrspace qualifier"); |
| 458 | 460 | }, |
| 459 | 461 | .extra_align_qualifier => { |
| 460 | | return stream.writeAll("extra align qualifier"); |
| 462 | return w.writeAll("extra align qualifier"); |
| 461 | 463 | }, |
| 462 | 464 | .extra_allowzero_qualifier => { |
| 463 | | return stream.writeAll("extra allowzero qualifier"); |
| 465 | return w.writeAll("extra allowzero qualifier"); |
| 464 | 466 | }, |
| 465 | 467 | .extra_const_qualifier => { |
| 466 | | return stream.writeAll("extra const qualifier"); |
| 468 | return w.writeAll("extra const qualifier"); |
| 467 | 469 | }, |
| 468 | 470 | .extra_volatile_qualifier => { |
| 469 | | return stream.writeAll("extra volatile qualifier"); |
| 471 | return w.writeAll("extra volatile qualifier"); |
| 470 | 472 | }, |
| 471 | 473 | .ptr_mod_on_array_child_type => { |
| 472 | | return stream.print("pointer modifier '{s}' not allowed on array child type", .{ |
| 474 | return w.print("pointer modifier '{s}' not allowed on array child type", .{ |
| 473 | 475 | tree.tokenTag(parse_error.token).symbol(), |
| 474 | 476 | }); |
| 475 | 477 | }, |
| 476 | 478 | .invalid_bit_range => { |
| 477 | | return stream.writeAll("bit range not allowed on slices and arrays"); |
| 479 | return w.writeAll("bit range not allowed on slices and arrays"); |
| 478 | 480 | }, |
| 479 | 481 | .same_line_doc_comment => { |
| 480 | | return stream.writeAll("same line documentation comment"); |
| 482 | return w.writeAll("same line documentation comment"); |
| 481 | 483 | }, |
| 482 | 484 | .unattached_doc_comment => { |
| 483 | | return stream.writeAll("unattached documentation comment"); |
| 485 | return w.writeAll("unattached documentation comment"); |
| 484 | 486 | }, |
| 485 | 487 | .test_doc_comment => { |
| 486 | | return stream.writeAll("documentation comments cannot be attached to tests"); |
| 488 | return w.writeAll("documentation comments cannot be attached to tests"); |
| 487 | 489 | }, |
| 488 | 490 | .comptime_doc_comment => { |
| 489 | | return stream.writeAll("documentation comments cannot be attached to comptime blocks"); |
| 491 | return w.writeAll("documentation comments cannot be attached to comptime blocks"); |
| 490 | 492 | }, |
| 491 | 493 | .varargs_nonfinal => { |
| 492 | | return stream.writeAll("function prototype has parameter after varargs"); |
| 494 | return w.writeAll("function prototype has parameter after varargs"); |
| 493 | 495 | }, |
| 494 | 496 | .expected_continue_expr => { |
| 495 | | return stream.writeAll("expected ':' before while continue expression"); |
| 497 | return w.writeAll("expected ':' before while continue expression"); |
| 496 | 498 | }, |
| 497 | 499 | |
| 498 | 500 | .expected_semi_after_decl => { |
| 499 | | return stream.writeAll("expected ';' after declaration"); |
| 501 | return w.writeAll("expected ';' after declaration"); |
| 500 | 502 | }, |
| 501 | 503 | .expected_semi_after_stmt => { |
| 502 | | return stream.writeAll("expected ';' after statement"); |
| 504 | return w.writeAll("expected ';' after statement"); |
| 503 | 505 | }, |
| 504 | 506 | .expected_comma_after_field => { |
| 505 | | return stream.writeAll("expected ',' after field"); |
| 507 | return w.writeAll("expected ',' after field"); |
| 506 | 508 | }, |
| 507 | 509 | .expected_comma_after_arg => { |
| 508 | | return stream.writeAll("expected ',' after argument"); |
| 510 | return w.writeAll("expected ',' after argument"); |
| 509 | 511 | }, |
| 510 | 512 | .expected_comma_after_param => { |
| 511 | | return stream.writeAll("expected ',' after parameter"); |
| 513 | return w.writeAll("expected ',' after parameter"); |
| 512 | 514 | }, |
| 513 | 515 | .expected_comma_after_initializer => { |
| 514 | | return stream.writeAll("expected ',' after initializer"); |
| 516 | return w.writeAll("expected ',' after initializer"); |
| 515 | 517 | }, |
| 516 | 518 | .expected_comma_after_switch_prong => { |
| 517 | | return stream.writeAll("expected ',' after switch prong"); |
| 519 | return w.writeAll("expected ',' after switch prong"); |
| 518 | 520 | }, |
| 519 | 521 | .expected_comma_after_for_operand => { |
| 520 | | return stream.writeAll("expected ',' after for operand"); |
| 522 | return w.writeAll("expected ',' after for operand"); |
| 521 | 523 | }, |
| 522 | 524 | .expected_comma_after_capture => { |
| 523 | | return stream.writeAll("expected ',' after for capture"); |
| 525 | return w.writeAll("expected ',' after for capture"); |
| 524 | 526 | }, |
| 525 | 527 | .expected_initializer => { |
| 526 | | return stream.writeAll("expected field initializer"); |
| 528 | return w.writeAll("expected field initializer"); |
| 527 | 529 | }, |
| 528 | 530 | .mismatched_binary_op_whitespace => { |
| 529 | | return stream.print("binary operator '{s}' has whitespace on one side, but not the other", .{tree.tokenTag(parse_error.token).lexeme().?}); |
| 531 | return w.print("binary operator '{s}' has whitespace on one side, but not the other", .{tree.tokenTag(parse_error.token).lexeme().?}); |
| 530 | 532 | }, |
| 531 | 533 | .invalid_ampersand_ampersand => { |
| 532 | | return stream.writeAll("ambiguous use of '&&'; use 'and' for logical AND, or change whitespace to ' & &' for bitwise AND"); |
| 534 | return w.writeAll("ambiguous use of '&&'; use 'and' for logical AND, or change whitespace to ' & &' for bitwise AND"); |
| 533 | 535 | }, |
| 534 | 536 | .c_style_container => { |
| 535 | | return stream.print("'{s} {s}' is invalid", .{ |
| 537 | return w.print("'{s} {s}' is invalid", .{ |
| 536 | 538 | parse_error.extra.expected_tag.symbol(), tree.tokenSlice(parse_error.token), |
| 537 | 539 | }); |
| 538 | 540 | }, |
| 539 | 541 | .zig_style_container => { |
| 540 | | return stream.print("to declare a container do 'const {s} = {s}'", .{ |
| 542 | return w.print("to declare a container do 'const {s} = {s}'", .{ |
| 541 | 543 | tree.tokenSlice(parse_error.token), parse_error.extra.expected_tag.symbol(), |
| 542 | 544 | }); |
| 543 | 545 | }, |
| 544 | 546 | .previous_field => { |
| 545 | | return stream.writeAll("field before declarations here"); |
| 547 | return w.writeAll("field before declarations here"); |
| 546 | 548 | }, |
| 547 | 549 | .next_field => { |
| 548 | | return stream.writeAll("field after declarations here"); |
| 550 | return w.writeAll("field after declarations here"); |
| 549 | 551 | }, |
| 550 | 552 | .expected_var_const => { |
| 551 | | return stream.writeAll("expected 'var' or 'const' before variable declaration"); |
| 553 | return w.writeAll("expected 'var' or 'const' before variable declaration"); |
| 552 | 554 | }, |
| 553 | 555 | .wrong_equal_var_decl => { |
| 554 | | return stream.writeAll("variable initialized with '==' instead of '='"); |
| 556 | return w.writeAll("variable initialized with '==' instead of '='"); |
| 555 | 557 | }, |
| 556 | 558 | .var_const_decl => { |
| 557 | | return stream.writeAll("use 'var' or 'const' to declare variable"); |
| 559 | return w.writeAll("use 'var' or 'const' to declare variable"); |
| 558 | 560 | }, |
| 559 | 561 | .extra_for_capture => { |
| 560 | | return stream.writeAll("extra capture in for loop"); |
| 562 | return w.writeAll("extra capture in for loop"); |
| 561 | 563 | }, |
| 562 | 564 | .for_input_not_captured => { |
| 563 | | return stream.writeAll("for input is not captured"); |
| 565 | return w.writeAll("for input is not captured"); |
| 564 | 566 | }, |
| 565 | 567 | |
| 566 | 568 | .invalid_byte => { |
| 567 | 569 | const tok_slice = tree.source[tree.tokens.items(.start)[parse_error.token]..]; |
| 568 | | return stream.print("{s} contains invalid byte: '{f}'", .{ |
| 570 | return w.print("{s} contains invalid byte: '{f}'", .{ |
| 569 | 571 | switch (tok_slice[0]) { |
| 570 | 572 | '\'' => "character literal", |
| 571 | 573 | '"', '\\' => "string literal", |
| ... | ... | @@ -580,10 +582,10 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void { |
| 580 | 582 | const found_tag = tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)); |
| 581 | 583 | const expected_symbol = parse_error.extra.expected_tag.symbol(); |
| 582 | 584 | switch (found_tag) { |
| 583 | | .invalid => return stream.print("expected '{s}', found invalid bytes", .{ |
| 585 | .invalid => return w.print("expected '{s}', found invalid bytes", .{ |
| 584 | 586 | expected_symbol, |
| 585 | 587 | }), |
| 586 | | else => return stream.print("expected '{s}', found '{s}'", .{ |
| 588 | else => return w.print("expected '{s}', found '{s}'", .{ |
| 587 | 589 | expected_symbol, found_tag.symbol(), |
| 588 | 590 | }), |
| 589 | 591 | } |
| ... | ... | @@ -4136,17 +4138,7 @@ pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex |
| 4136 | 4138 | return Span{ .start = start_off, .end = end_off, .main = tree.tokenStart(main) }; |
| 4137 | 4139 | } |
| 4138 | 4140 | |
| 4139 | | const std = @import("../std.zig"); |
| 4140 | | const assert = std.debug.assert; |
| 4141 | | const testing = std.testing; |
| 4142 | | const mem = std.mem; |
| 4143 | | const Token = std.zig.Token; |
| 4144 | | const Ast = @This(); |
| 4145 | | const Allocator = std.mem.Allocator; |
| 4146 | | const Parse = @import("Parse.zig"); |
| 4147 | | const private_render = @import("./render.zig"); |
| 4148 | | |
| 4149 | 4141 | test { |
| 4150 | 4142 | _ = Parse; |
| 4151 | | _ = private_render; |
| 4143 | _ = Render; |
| 4152 | 4144 | } |