authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-15 21:12:05-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-16 17:20:02-07:00
log6c4a104822679e92e094b166cc11b56b43f84a33
tree144422948210c4bf9c58279c7bad52bd5c3539d8
parent1a20b467ea3f480306317a6145d910d8c44a9b48

std.zig.Ast: update to new I/O API


1 files changed, 89 insertions(+), 97 deletions(-)

lib/std/zig/Ast.zig+89-97
...@@ -4,6 +4,16 @@...@@ -4,6 +4,16 @@
4//! For Zon syntax, the root node is at nodes[0] and contains lhs as the node4//! For Zon syntax, the root node is at nodes[0] and contains lhs as the node
5//! index of the main expression.5//! index of the main expression.
66
7const std = @import("../std.zig");
8const assert = std.debug.assert;
9const testing = std.testing;
10const mem = std.mem;
11const Token = std.zig.Token;
12const Ast = @This();
13const Allocator = std.mem.Allocator;
14const Parse = @import("Parse.zig");
15const Writer = std.Io.Writer;
16
7/// Reference to externally-owned data.17/// Reference to externally-owned data.
8source: [:0]const u8,18source: [:0]const u8,
919
...@@ -128,12 +138,6 @@ pub fn deinit(tree: *Ast, gpa: Allocator) void {...@@ -128,12 +138,6 @@ pub fn deinit(tree: *Ast, gpa: Allocator) void {
128 tree.* = undefined;138 tree.* = undefined;
129}139}
130140
131pub 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
137pub const Mode = enum { zig, zon };141pub const Mode = enum { zig, zon };
138142
139/// Result should be freed with tree.deinit() when there are143/// 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,27 +203,25 @@ pub fn parse(gpa: Allocator, source: [:0]const u8, mode: Mode) Allocator.Error!A
199203
200/// `gpa` is used for allocating the resulting formatted source code.204/// `gpa` is used for allocating the resulting formatted source code.
201/// Caller owns the returned slice of bytes, allocated with `gpa`.205/// Caller owns the returned slice of bytes, allocated with `gpa`.
202pub fn render(tree: Ast, gpa: Allocator) RenderError![]u8 {206pub fn renderAlloc(tree: Ast, gpa: Allocator) error{OutOfMemory}![]u8 {
203 var buffer = std.ArrayList(u8).init(gpa);207 var aw: std.io.Writer.Allocating = .init(gpa);
204 defer buffer.deinit();208 defer aw.deinit();
205209 render(tree, gpa, &aw.writer, .{}) catch |err| switch (err) {
206 try tree.renderToArrayList(&buffer, .{});210 error.WriteFailed => return error.OutOfMemory,
207 return buffer.toOwnedSlice();211 };
212 return aw.toOwnedSlice();
208}213}
209214
210pub const Fixups = private_render.Fixups;215pub const Render = @import("Ast/Render.zig");
211216
212pub fn renderToArrayList(tree: Ast, buffer: *std.ArrayList(u8), fixups: Fixups) RenderError!void {217pub fn render(tree: Ast, gpa: Allocator, w: *Writer, fixups: Render.Fixups) Render.Error!void {
213 return @import("./render.zig").renderTree(buffer, tree, fixups);218 return Render.tree(gpa, w, tree, fixups);
214}219}
215220
216/// Returns an extra offset for column and byte offset of errors that221/// Returns an extra offset for column and byte offset of errors that
217/// should point after the token in the error message.222/// should point after the token in the error message.
218pub fn errorOffset(tree: Ast, parse_error: Error) u32 {223pub fn errorOffset(tree: Ast, parse_error: Error) u32 {
219 return if (parse_error.token_is_prev)224 return if (parse_error.token_is_prev) @intCast(tree.tokenSlice(parse_error.token).len) else 0;
220 @as(u32, @intCast(tree.tokenSlice(parse_error.token).len))
221 else
222 0;
223}225}
224226
225pub fn tokenLocation(self: Ast, start_offset: ByteOffset, token_index: TokenIndex) Location {227pub fn tokenLocation(self: Ast, start_offset: ByteOffset, token_index: TokenIndex) Location {
...@@ -318,254 +320,254 @@ pub fn rootDecls(tree: Ast) []const Node.Index {...@@ -318,254 +320,254 @@ pub fn rootDecls(tree: Ast) []const Node.Index {
318 }320 }
319}321}
320322
321pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {323pub fn renderError(tree: Ast, parse_error: Error, w: *Writer) Writer.Error!void {
322 switch (parse_error.tag) {324 switch (parse_error.tag) {
323 .asterisk_after_ptr_deref => {325 .asterisk_after_ptr_deref => {
324 // Note that the token will point at the `.*` but ideally the source326 // Note that the token will point at the `.*` but ideally the source
325 // location would point to the `*` after the `.*`.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 .chained_comparison_operators => {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 .decl_between_fields => {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 .expected_block => {336 .expected_block => {
335 return stream.print("expected block, found '{s}'", .{337 return w.print("expected block, found '{s}'", .{
336 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),338 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
337 });339 });
338 },340 },
339 .expected_block_or_assignment => {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 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),343 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
342 });344 });
343 },345 },
344 .expected_block_or_expr => {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 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),348 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
347 });349 });
348 },350 },
349 .expected_block_or_field => {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 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),353 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
352 });354 });
353 },355 },
354 .expected_container_members => {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 tree.tokenTag(parse_error.token).symbol(),358 tree.tokenTag(parse_error.token).symbol(),
357 });359 });
358 },360 },
359 .expected_expr => {361 .expected_expr => {
360 return stream.print("expected expression, found '{s}'", .{362 return w.print("expected expression, found '{s}'", .{
361 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),363 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
362 });364 });
363 },365 },
364 .expected_expr_or_assignment => {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 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),368 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
367 });369 });
368 },370 },
369 .expected_expr_or_var_decl => {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 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),373 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
372 });374 });
373 },375 },
374 .expected_fn => {376 .expected_fn => {
375 return stream.print("expected function, found '{s}'", .{377 return w.print("expected function, found '{s}'", .{
376 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),378 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
377 });379 });
378 },380 },
379 .expected_inlinable => {381 .expected_inlinable => {
380 return stream.print("expected 'while' or 'for', found '{s}'", .{382 return w.print("expected 'while' or 'for', found '{s}'", .{
381 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),383 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
382 });384 });
383 },385 },
384 .expected_labelable => {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 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),388 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
387 });389 });
388 },390 },
389 .expected_param_list => {391 .expected_param_list => {
390 return stream.print("expected parameter list, found '{s}'", .{392 return w.print("expected parameter list, found '{s}'", .{
391 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),393 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
392 });394 });
393 },395 },
394 .expected_prefix_expr => {396 .expected_prefix_expr => {
395 return stream.print("expected prefix expression, found '{s}'", .{397 return w.print("expected prefix expression, found '{s}'", .{
396 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),398 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
397 });399 });
398 },400 },
399 .expected_primary_type_expr => {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 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),403 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
402 });404 });
403 },405 },
404 .expected_pub_item => {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 .expected_return_type => {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 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),411 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
410 });412 });
411 },413 },
412 .expected_semi_or_else => {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 .expected_semi_or_lbrace => {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 .expected_statement => {420 .expected_statement => {
419 return stream.print("expected statement, found '{s}'", .{421 return w.print("expected statement, found '{s}'", .{
420 tree.tokenTag(parse_error.token).symbol(),422 tree.tokenTag(parse_error.token).symbol(),
421 });423 });
422 },424 },
423 .expected_suffix_op => {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 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),427 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
426 });428 });
427 },429 },
428 .expected_type_expr => {430 .expected_type_expr => {
429 return stream.print("expected type expression, found '{s}'", .{431 return w.print("expected type expression, found '{s}'", .{
430 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),432 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
431 });433 });
432 },434 },
433 .expected_var_decl => {435 .expected_var_decl => {
434 return stream.print("expected variable declaration, found '{s}'", .{436 return w.print("expected variable declaration, found '{s}'", .{
435 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),437 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
436 });438 });
437 },439 },
438 .expected_var_decl_or_fn => {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 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),442 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
441 });443 });
442 },444 },
443 .expected_loop_payload => {445 .expected_loop_payload => {
444 return stream.print("expected loop payload, found '{s}'", .{446 return w.print("expected loop payload, found '{s}'", .{
445 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),447 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
446 });448 });
447 },449 },
448 .expected_container => {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 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),452 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
451 });453 });
452 },454 },
453 .extern_fn_body => {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 .extra_addrspace_qualifier => {458 .extra_addrspace_qualifier => {
457 return stream.writeAll("extra addrspace qualifier");459 return w.writeAll("extra addrspace qualifier");
458 },460 },
459 .extra_align_qualifier => {461 .extra_align_qualifier => {
460 return stream.writeAll("extra align qualifier");462 return w.writeAll("extra align qualifier");
461 },463 },
462 .extra_allowzero_qualifier => {464 .extra_allowzero_qualifier => {
463 return stream.writeAll("extra allowzero qualifier");465 return w.writeAll("extra allowzero qualifier");
464 },466 },
465 .extra_const_qualifier => {467 .extra_const_qualifier => {
466 return stream.writeAll("extra const qualifier");468 return w.writeAll("extra const qualifier");
467 },469 },
468 .extra_volatile_qualifier => {470 .extra_volatile_qualifier => {
469 return stream.writeAll("extra volatile qualifier");471 return w.writeAll("extra volatile qualifier");
470 },472 },
471 .ptr_mod_on_array_child_type => {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 tree.tokenTag(parse_error.token).symbol(),475 tree.tokenTag(parse_error.token).symbol(),
474 });476 });
475 },477 },
476 .invalid_bit_range => {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 .same_line_doc_comment => {481 .same_line_doc_comment => {
480 return stream.writeAll("same line documentation comment");482 return w.writeAll("same line documentation comment");
481 },483 },
482 .unattached_doc_comment => {484 .unattached_doc_comment => {
483 return stream.writeAll("unattached documentation comment");485 return w.writeAll("unattached documentation comment");
484 },486 },
485 .test_doc_comment => {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 .comptime_doc_comment => {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 .varargs_nonfinal => {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 .expected_continue_expr => {496 .expected_continue_expr => {
495 return stream.writeAll("expected ':' before while continue expression");497 return w.writeAll("expected ':' before while continue expression");
496 },498 },
497499
498 .expected_semi_after_decl => {500 .expected_semi_after_decl => {
499 return stream.writeAll("expected ';' after declaration");501 return w.writeAll("expected ';' after declaration");
500 },502 },
501 .expected_semi_after_stmt => {503 .expected_semi_after_stmt => {
502 return stream.writeAll("expected ';' after statement");504 return w.writeAll("expected ';' after statement");
503 },505 },
504 .expected_comma_after_field => {506 .expected_comma_after_field => {
505 return stream.writeAll("expected ',' after field");507 return w.writeAll("expected ',' after field");
506 },508 },
507 .expected_comma_after_arg => {509 .expected_comma_after_arg => {
508 return stream.writeAll("expected ',' after argument");510 return w.writeAll("expected ',' after argument");
509 },511 },
510 .expected_comma_after_param => {512 .expected_comma_after_param => {
511 return stream.writeAll("expected ',' after parameter");513 return w.writeAll("expected ',' after parameter");
512 },514 },
513 .expected_comma_after_initializer => {515 .expected_comma_after_initializer => {
514 return stream.writeAll("expected ',' after initializer");516 return w.writeAll("expected ',' after initializer");
515 },517 },
516 .expected_comma_after_switch_prong => {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 .expected_comma_after_for_operand => {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 .expected_comma_after_capture => {524 .expected_comma_after_capture => {
523 return stream.writeAll("expected ',' after for capture");525 return w.writeAll("expected ',' after for capture");
524 },526 },
525 .expected_initializer => {527 .expected_initializer => {
526 return stream.writeAll("expected field initializer");528 return w.writeAll("expected field initializer");
527 },529 },
528 .mismatched_binary_op_whitespace => {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 .invalid_ampersand_ampersand => {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 .c_style_container => {536 .c_style_container => {
535 return stream.print("'{s} {s}' is invalid", .{537 return w.print("'{s} {s}' is invalid", .{
536 parse_error.extra.expected_tag.symbol(), tree.tokenSlice(parse_error.token),538 parse_error.extra.expected_tag.symbol(), tree.tokenSlice(parse_error.token),
537 });539 });
538 },540 },
539 .zig_style_container => {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 tree.tokenSlice(parse_error.token), parse_error.extra.expected_tag.symbol(),543 tree.tokenSlice(parse_error.token), parse_error.extra.expected_tag.symbol(),
542 });544 });
543 },545 },
544 .previous_field => {546 .previous_field => {
545 return stream.writeAll("field before declarations here");547 return w.writeAll("field before declarations here");
546 },548 },
547 .next_field => {549 .next_field => {
548 return stream.writeAll("field after declarations here");550 return w.writeAll("field after declarations here");
549 },551 },
550 .expected_var_const => {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 .wrong_equal_var_decl => {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 .var_const_decl => {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 .extra_for_capture => {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 .for_input_not_captured => {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 },
565567
566 .invalid_byte => {568 .invalid_byte => {
567 const tok_slice = tree.source[tree.tokens.items(.start)[parse_error.token]..];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 switch (tok_slice[0]) {571 switch (tok_slice[0]) {
570 '\'' => "character literal",572 '\'' => "character literal",
571 '"', '\\' => "string literal",573 '"', '\\' => "string literal",
...@@ -580,10 +582,10 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {...@@ -580,10 +582,10 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
580 const found_tag = tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev));582 const found_tag = tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev));
581 const expected_symbol = parse_error.extra.expected_tag.symbol();583 const expected_symbol = parse_error.extra.expected_tag.symbol();
582 switch (found_tag) {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 expected_symbol,586 expected_symbol,
585 }),587 }),
586 else => return stream.print("expected '{s}', found '{s}'", .{588 else => return w.print("expected '{s}', found '{s}'", .{
587 expected_symbol, found_tag.symbol(),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,17 +4138,7 @@ pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex
4136 return Span{ .start = start_off, .end = end_off, .main = tree.tokenStart(main) };4138 return Span{ .start = start_off, .end = end_off, .main = tree.tokenStart(main) };
4137}4139}
41384140
4139const std = @import("../std.zig");
4140const assert = std.debug.assert;
4141const testing = std.testing;
4142const mem = std.mem;
4143const Token = std.zig.Token;
4144const Ast = @This();
4145const Allocator = std.mem.Allocator;
4146const Parse = @import("Parse.zig");
4147const private_render = @import("./render.zig");
4148
4149test {4141test {
4150 _ = Parse;4142 _ = Parse;
4151 _ = private_render;4143 _ = Render;
4152}4144}