| ... | ... | @@ -182,6 +182,11 @@ pub const Parser = struct { |
| 182 | 182 | } |
| 183 | 183 | }; |
| 184 | 184 | |
| 185 | const AddCommentsCtx = struct { |
| 186 | node_ptr: &&ast.Node, |
| 187 | comments: ?&ast.Node.LineComment, |
| 188 | }; |
| 189 | |
| 185 | 190 | const State = union(enum) { |
| 186 | 191 | TopLevel, |
| 187 | 192 | TopLevelExtern: TopLevelDeclCtx, |
| ... | ... | @@ -221,6 +226,7 @@ pub const Parser = struct { |
| 221 | 226 | Statement: &ast.Node.Block, |
| 222 | 227 | ComptimeStatement: ComptimeStatementCtx, |
| 223 | 228 | Semicolon: &&ast.Node, |
| 229 | AddComments: AddCommentsCtx, |
| 224 | 230 | |
| 225 | 231 | AsmOutputItems: &ArrayList(&ast.Node.AsmOutput), |
| 226 | 232 | AsmOutputReturnOrType: &ast.Node.AsmOutput, |
| ... | ... | @@ -345,24 +351,26 @@ pub const Parser = struct { |
| 345 | 351 | Token.Id.Keyword_test => { |
| 346 | 352 | stack.append(State.TopLevel) catch unreachable; |
| 347 | 353 | |
| 348 | | const block = try self.createNode(arena, ast.Node.Block, |
| 349 | | ast.Node.Block { |
| 350 | | .base = undefined, |
| 351 | | .label = null, |
| 352 | | .lbrace = undefined, |
| 353 | | .statements = ArrayList(&ast.Node).init(arena), |
| 354 | | .rbrace = undefined, |
| 355 | | } |
| 356 | | ); |
| 357 | | const test_node = try self.createAttachNode(arena, &root_node.decls, ast.Node.TestDecl, |
| 358 | | ast.Node.TestDecl { |
| 359 | | .base = undefined, |
| 354 | const block = try arena.construct(ast.Node.Block { |
| 355 | .base = ast.Node { |
| 356 | .id = ast.Node.Id.Block, |
| 357 | .comments = null, |
| 358 | }, |
| 359 | .label = null, |
| 360 | .lbrace = undefined, |
| 361 | .statements = ArrayList(&ast.Node).init(arena), |
| 362 | .rbrace = undefined, |
| 363 | }); |
| 364 | const test_node = try arena.construct(ast.Node.TestDecl { |
| 365 | .base = ast.Node { |
| 366 | .id = ast.Node.Id.TestDecl, |
| 360 | 367 | .comments = comments, |
| 361 | | .test_token = token, |
| 362 | | .name = undefined, |
| 363 | | .body_node = &block.base, |
| 364 | | } |
| 365 | | ); |
| 368 | }, |
| 369 | .test_token = token, |
| 370 | .name = undefined, |
| 371 | .body_node = &block.base, |
| 372 | }); |
| 373 | try root_node.decls.append(&test_node.base); |
| 366 | 374 | stack.append(State { .Block = block }) catch unreachable; |
| 367 | 375 | try stack.append(State { |
| 368 | 376 | .ExpectTokenSave = ExpectTokenSave { |
| ... | ... | @@ -530,24 +538,25 @@ pub const Parser = struct { |
| 530 | 538 | }, |
| 531 | 539 | Token.Id.Keyword_fn, Token.Id.Keyword_nakedcc, |
| 532 | 540 | Token.Id.Keyword_stdcallcc, Token.Id.Keyword_async => { |
| 533 | | const fn_proto = try self.createAttachNode(arena, ctx.decls, ast.Node.FnProto, |
| 534 | | ast.Node.FnProto { |
| 535 | | .base = undefined, |
| 541 | const fn_proto = try arena.construct(ast.Node.FnProto { |
| 542 | .base = ast.Node { |
| 543 | .id = ast.Node.Id.FnProto, |
| 536 | 544 | .comments = comments, |
| 537 | | .visib_token = ctx.visib_token, |
| 538 | | .name_token = null, |
| 539 | | .fn_token = undefined, |
| 540 | | .params = ArrayList(&ast.Node).init(arena), |
| 541 | | .return_type = undefined, |
| 542 | | .var_args_token = null, |
| 543 | | .extern_export_inline_token = ctx.extern_export_inline_token, |
| 544 | | .cc_token = null, |
| 545 | | .async_attr = null, |
| 546 | | .body_node = null, |
| 547 | | .lib_name = ctx.lib_name, |
| 548 | | .align_expr = null, |
| 549 | | } |
| 550 | | ); |
| 545 | }, |
| 546 | .visib_token = ctx.visib_token, |
| 547 | .name_token = null, |
| 548 | .fn_token = undefined, |
| 549 | .params = ArrayList(&ast.Node).init(arena), |
| 550 | .return_type = undefined, |
| 551 | .var_args_token = null, |
| 552 | .extern_export_inline_token = ctx.extern_export_inline_token, |
| 553 | .cc_token = null, |
| 554 | .async_attr = null, |
| 555 | .body_node = null, |
| 556 | .lib_name = ctx.lib_name, |
| 557 | .align_expr = null, |
| 558 | }); |
| 559 | try ctx.decls.append(&fn_proto.base); |
| 551 | 560 | stack.append(State { .FnDef = fn_proto }) catch unreachable; |
| 552 | 561 | try stack.append(State { .FnProto = fn_proto }); |
| 553 | 562 | |
| ... | ... | @@ -789,24 +798,25 @@ pub const Parser = struct { |
| 789 | 798 | |
| 790 | 799 | |
| 791 | 800 | State.VarDecl => |ctx| { |
| 792 | | const var_decl = try self.createAttachNode(arena, ctx.list, ast.Node.VarDecl, |
| 793 | | ast.Node.VarDecl { |
| 794 | | .base = undefined, |
| 801 | const var_decl = try arena.construct(ast.Node.VarDecl { |
| 802 | .base = ast.Node { |
| 803 | .id = ast.Node.Id.VarDecl, |
| 795 | 804 | .comments = ctx.comments, |
| 796 | | .visib_token = ctx.visib_token, |
| 797 | | .mut_token = ctx.mut_token, |
| 798 | | .comptime_token = ctx.comptime_token, |
| 799 | | .extern_export_token = ctx.extern_export_token, |
| 800 | | .type_node = null, |
| 801 | | .align_node = null, |
| 802 | | .init_node = null, |
| 803 | | .lib_name = ctx.lib_name, |
| 804 | | // initialized later |
| 805 | | .name_token = undefined, |
| 806 | | .eq_token = undefined, |
| 807 | | .semicolon_token = undefined, |
| 808 | | } |
| 809 | | ); |
| 805 | }, |
| 806 | .visib_token = ctx.visib_token, |
| 807 | .mut_token = ctx.mut_token, |
| 808 | .comptime_token = ctx.comptime_token, |
| 809 | .extern_export_token = ctx.extern_export_token, |
| 810 | .type_node = null, |
| 811 | .align_node = null, |
| 812 | .init_node = null, |
| 813 | .lib_name = ctx.lib_name, |
| 814 | // initialized later |
| 815 | .name_token = undefined, |
| 816 | .eq_token = undefined, |
| 817 | .semicolon_token = undefined, |
| 818 | }); |
| 819 | try ctx.list.append(&var_decl.base); |
| 810 | 820 | |
| 811 | 821 | stack.append(State { .VarDeclAlign = var_decl }) catch unreachable; |
| 812 | 822 | try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &var_decl.type_node} }); |
| ... | ... | @@ -1218,19 +1228,23 @@ pub const Parser = struct { |
| 1218 | 1228 | continue; |
| 1219 | 1229 | }, |
| 1220 | 1230 | Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => { |
| 1221 | | const node = try self.createAttachNode(arena, &block.statements, ast.Node.Defer, |
| 1222 | | ast.Node.Defer { |
| 1223 | | .base = undefined, |
| 1224 | | .defer_token = token, |
| 1225 | | .kind = switch (token.id) { |
| 1226 | | Token.Id.Keyword_defer => ast.Node.Defer.Kind.Unconditional, |
| 1227 | | Token.Id.Keyword_errdefer => ast.Node.Defer.Kind.Error, |
| 1228 | | else => unreachable, |
| 1229 | | }, |
| 1230 | | .expr = undefined, |
| 1231 | | } |
| 1232 | | ); |
| 1233 | | stack.append(State { .Semicolon = &&node.base }) catch unreachable; |
| 1231 | const node = try arena.construct(ast.Node.Defer { |
| 1232 | .base = ast.Node { |
| 1233 | .id = ast.Node.Id.Defer, |
| 1234 | .comments = comments, |
| 1235 | }, |
| 1236 | .defer_token = token, |
| 1237 | .kind = switch (token.id) { |
| 1238 | Token.Id.Keyword_defer => ast.Node.Defer.Kind.Unconditional, |
| 1239 | Token.Id.Keyword_errdefer => ast.Node.Defer.Kind.Error, |
| 1240 | else => unreachable, |
| 1241 | }, |
| 1242 | .expr = undefined, |
| 1243 | }); |
| 1244 | const node_ptr = try block.statements.addOne(); |
| 1245 | *node_ptr = &node.base; |
| 1246 | |
| 1247 | stack.append(State { .Semicolon = node_ptr }) catch unreachable; |
| 1234 | 1248 | try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } }); |
| 1235 | 1249 | continue; |
| 1236 | 1250 | }, |
| ... | ... | @@ -1249,9 +1263,13 @@ pub const Parser = struct { |
| 1249 | 1263 | }, |
| 1250 | 1264 | else => { |
| 1251 | 1265 | self.putBackToken(token); |
| 1252 | | const statememt = try block.statements.addOne(); |
| 1253 | | stack.append(State { .Semicolon = statememt }) catch unreachable; |
| 1254 | | try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = statememt } }); |
| 1266 | const statement = try block.statements.addOne(); |
| 1267 | stack.append(State { .Semicolon = statement }) catch unreachable; |
| 1268 | try stack.append(State { .AddComments = AddCommentsCtx { |
| 1269 | .node_ptr = statement, |
| 1270 | .comments = comments, |
| 1271 | }}); |
| 1272 | try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = statement } }); |
| 1255 | 1273 | continue; |
| 1256 | 1274 | } |
| 1257 | 1275 | } |
| ... | ... | @@ -1293,6 +1311,12 @@ pub const Parser = struct { |
| 1293 | 1311 | continue; |
| 1294 | 1312 | }, |
| 1295 | 1313 | |
| 1314 | State.AddComments => |add_comments_ctx| { |
| 1315 | const node = *add_comments_ctx.node_ptr; |
| 1316 | node.comments = add_comments_ctx.comments; |
| 1317 | continue; |
| 1318 | }, |
| 1319 | |
| 1296 | 1320 | |
| 1297 | 1321 | State.AsmOutputItems => |items| { |
| 1298 | 1322 | const lbracket = self.getNextToken(); |
| ... | ... | @@ -1576,24 +1600,25 @@ pub const Parser = struct { |
| 1576 | 1600 | |
| 1577 | 1601 | State.ExternType => |ctx| { |
| 1578 | 1602 | if (self.eatToken(Token.Id.Keyword_fn)) |fn_token| { |
| 1579 | | const fn_proto = try self.createToCtxNode(arena, ctx.opt_ctx, ast.Node.FnProto, |
| 1580 | | ast.Node.FnProto { |
| 1581 | | .base = undefined, |
| 1603 | const fn_proto = try arena.construct(ast.Node.FnProto { |
| 1604 | .base = ast.Node { |
| 1605 | .id = ast.Node.Id.FnProto, |
| 1582 | 1606 | .comments = ctx.comments, |
| 1583 | | .visib_token = null, |
| 1584 | | .name_token = null, |
| 1585 | | .fn_token = fn_token, |
| 1586 | | .params = ArrayList(&ast.Node).init(arena), |
| 1587 | | .return_type = undefined, |
| 1588 | | .var_args_token = null, |
| 1589 | | .extern_export_inline_token = ctx.extern_token, |
| 1590 | | .cc_token = null, |
| 1591 | | .async_attr = null, |
| 1592 | | .body_node = null, |
| 1593 | | .lib_name = null, |
| 1594 | | .align_expr = null, |
| 1595 | | } |
| 1596 | | ); |
| 1607 | }, |
| 1608 | .visib_token = null, |
| 1609 | .name_token = null, |
| 1610 | .fn_token = fn_token, |
| 1611 | .params = ArrayList(&ast.Node).init(arena), |
| 1612 | .return_type = undefined, |
| 1613 | .var_args_token = null, |
| 1614 | .extern_export_inline_token = ctx.extern_token, |
| 1615 | .cc_token = null, |
| 1616 | .async_attr = null, |
| 1617 | .body_node = null, |
| 1618 | .lib_name = null, |
| 1619 | .align_expr = null, |
| 1620 | }); |
| 1621 | ctx.opt_ctx.store(&fn_proto.base); |
| 1597 | 1622 | stack.append(State { .FnProto = fn_proto }) catch unreachable; |
| 1598 | 1623 | continue; |
| 1599 | 1624 | } |
| ... | ... | @@ -2546,46 +2571,48 @@ pub const Parser = struct { |
| 2546 | 2571 | continue; |
| 2547 | 2572 | }, |
| 2548 | 2573 | Token.Id.Keyword_fn => { |
| 2549 | | const fn_proto = try self.createToCtxNode(arena, opt_ctx, ast.Node.FnProto, |
| 2550 | | ast.Node.FnProto { |
| 2551 | | .base = undefined, |
| 2574 | const fn_proto = try arena.construct(ast.Node.FnProto { |
| 2575 | .base = ast.Node { |
| 2576 | .id = ast.Node.Id.FnProto, |
| 2552 | 2577 | .comments = null, |
| 2553 | | .visib_token = null, |
| 2554 | | .name_token = null, |
| 2555 | | .fn_token = token, |
| 2556 | | .params = ArrayList(&ast.Node).init(arena), |
| 2557 | | .return_type = undefined, |
| 2558 | | .var_args_token = null, |
| 2559 | | .extern_export_inline_token = null, |
| 2560 | | .cc_token = null, |
| 2561 | | .async_attr = null, |
| 2562 | | .body_node = null, |
| 2563 | | .lib_name = null, |
| 2564 | | .align_expr = null, |
| 2565 | | } |
| 2566 | | ); |
| 2578 | }, |
| 2579 | .visib_token = null, |
| 2580 | .name_token = null, |
| 2581 | .fn_token = token, |
| 2582 | .params = ArrayList(&ast.Node).init(arena), |
| 2583 | .return_type = undefined, |
| 2584 | .var_args_token = null, |
| 2585 | .extern_export_inline_token = null, |
| 2586 | .cc_token = null, |
| 2587 | .async_attr = null, |
| 2588 | .body_node = null, |
| 2589 | .lib_name = null, |
| 2590 | .align_expr = null, |
| 2591 | }); |
| 2592 | opt_ctx.store(&fn_proto.base); |
| 2567 | 2593 | stack.append(State { .FnProto = fn_proto }) catch unreachable; |
| 2568 | 2594 | continue; |
| 2569 | 2595 | }, |
| 2570 | 2596 | Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => { |
| 2571 | | const fn_proto = try self.createToCtxNode(arena, opt_ctx, ast.Node.FnProto, |
| 2572 | | ast.Node.FnProto { |
| 2573 | | .base = undefined, |
| 2597 | const fn_proto = try arena.construct(ast.Node.FnProto { |
| 2598 | .base = ast.Node { |
| 2599 | .id = ast.Node.Id.FnProto, |
| 2574 | 2600 | .comments = null, |
| 2575 | | .visib_token = null, |
| 2576 | | .name_token = null, |
| 2577 | | .fn_token = undefined, |
| 2578 | | .params = ArrayList(&ast.Node).init(arena), |
| 2579 | | .return_type = undefined, |
| 2580 | | .var_args_token = null, |
| 2581 | | .extern_export_inline_token = null, |
| 2582 | | .cc_token = token, |
| 2583 | | .async_attr = null, |
| 2584 | | .body_node = null, |
| 2585 | | .lib_name = null, |
| 2586 | | .align_expr = null, |
| 2587 | | } |
| 2588 | | ); |
| 2601 | }, |
| 2602 | .visib_token = null, |
| 2603 | .name_token = null, |
| 2604 | .fn_token = undefined, |
| 2605 | .params = ArrayList(&ast.Node).init(arena), |
| 2606 | .return_type = undefined, |
| 2607 | .var_args_token = null, |
| 2608 | .extern_export_inline_token = null, |
| 2609 | .cc_token = token, |
| 2610 | .async_attr = null, |
| 2611 | .body_node = null, |
| 2612 | .lib_name = null, |
| 2613 | .align_expr = null, |
| 2614 | }); |
| 2615 | opt_ctx.store(&fn_proto.base); |
| 2589 | 2616 | stack.append(State { .FnProto = fn_proto }) catch unreachable; |
| 2590 | 2617 | try stack.append(State { |
| 2591 | 2618 | .ExpectTokenSave = ExpectTokenSave { |
| ... | ... | @@ -2747,13 +2774,13 @@ pub const Parser = struct { |
| 2747 | 2774 | if (result) |comment_node| { |
| 2748 | 2775 | break :blk comment_node; |
| 2749 | 2776 | } else { |
| 2750 | | const comment_node = try arena.create(ast.Node.LineComment); |
| 2751 | | *comment_node = ast.Node.LineComment { |
| 2777 | const comment_node = try arena.construct(ast.Node.LineComment { |
| 2752 | 2778 | .base = ast.Node { |
| 2753 | 2779 | .id = ast.Node.Id.LineComment, |
| 2780 | .comments = null, |
| 2754 | 2781 | }, |
| 2755 | 2782 | .lines = ArrayList(Token).init(arena), |
| 2756 | | }; |
| 2783 | }); |
| 2757 | 2784 | result = comment_node; |
| 2758 | 2785 | break :blk comment_node; |
| 2759 | 2786 | } |
| ... | ... | @@ -3096,7 +3123,7 @@ pub const Parser = struct { |
| 3096 | 3123 | *node = *init_to; |
| 3097 | 3124 | node.base = blk: { |
| 3098 | 3125 | const id = ast.Node.typeToId(T); |
| 3099 | | break :blk ast.Node {.id = id}; |
| 3126 | break :blk ast.Node {.id = id, .comments = null}; |
| 3100 | 3127 | }; |
| 3101 | 3128 | |
| 3102 | 3129 | return node; |
| ... | ... | @@ -3269,7 +3296,7 @@ pub const Parser = struct { |
| 3269 | 3296 | switch (decl.id) { |
| 3270 | 3297 | ast.Node.Id.FnProto => { |
| 3271 | 3298 | const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); |
| 3272 | | try self.renderComments(stream, fn_proto, indent); |
| 3299 | try self.renderComments(stream, &fn_proto.base, indent); |
| 3273 | 3300 | |
| 3274 | 3301 | if (fn_proto.body_node) |body_node| { |
| 3275 | 3302 | stack.append(RenderState { .Expression = body_node}) catch unreachable; |
| ... | ... | @@ -3295,7 +3322,7 @@ pub const Parser = struct { |
| 3295 | 3322 | }, |
| 3296 | 3323 | ast.Node.Id.TestDecl => { |
| 3297 | 3324 | const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl); |
| 3298 | | try self.renderComments(stream, test_decl, indent); |
| 3325 | try self.renderComments(stream, &test_decl.base, indent); |
| 3299 | 3326 | try stream.print("test "); |
| 3300 | 3327 | try stack.append(RenderState { .Expression = test_decl.body_node }); |
| 3301 | 3328 | try stack.append(RenderState { .Text = " " }); |
| ... | ... | @@ -3338,7 +3365,6 @@ pub const Parser = struct { |
| 3338 | 3365 | }, |
| 3339 | 3366 | |
| 3340 | 3367 | RenderState.FieldInitializer => |field_init| { |
| 3341 | | //TODO try self.renderComments(stream, field_init, indent); |
| 3342 | 3368 | try stream.print(".{}", self.tokenizer.getTokenSlice(field_init.name_token)); |
| 3343 | 3369 | try stream.print(" = "); |
| 3344 | 3370 | try stack.append(RenderState { .Expression = field_init.expr }); |
| ... | ... | @@ -3385,7 +3411,6 @@ pub const Parser = struct { |
| 3385 | 3411 | |
| 3386 | 3412 | RenderState.ParamDecl => |base| { |
| 3387 | 3413 | const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base); |
| 3388 | | // TODO try self.renderComments(stream, param_decl, indent); |
| 3389 | 3414 | if (param_decl.comptime_token) |comptime_token| { |
| 3390 | 3415 | try stream.print("{} ", self.tokenizer.getTokenSlice(comptime_token)); |
| 3391 | 3416 | } |
| ... | ... | @@ -4328,10 +4353,10 @@ pub const Parser = struct { |
| 4328 | 4353 | ast.Node.Id.ParamDecl => unreachable, |
| 4329 | 4354 | }, |
| 4330 | 4355 | RenderState.Statement => |base| { |
| 4356 | try self.renderComments(stream, base, indent); |
| 4331 | 4357 | switch (base.id) { |
| 4332 | 4358 | ast.Node.Id.VarDecl => { |
| 4333 | 4359 | const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base); |
| 4334 | | try self.renderComments(stream, var_decl, indent); |
| 4335 | 4360 | try stack.append(RenderState { .VarDecl = var_decl}); |
| 4336 | 4361 | }, |
| 4337 | 4362 | else => { |
| ... | ... | @@ -4348,7 +4373,7 @@ pub const Parser = struct { |
| 4348 | 4373 | } |
| 4349 | 4374 | } |
| 4350 | 4375 | |
| 4351 | | fn renderComments(self: &Parser, stream: var, node: var, indent: usize) !void { |
| 4376 | fn renderComments(self: &Parser, stream: var, node: &ast.Node, indent: usize) !void { |
| 4352 | 4377 | const comment = node.comments ?? return; |
| 4353 | 4378 | for (comment.lines.toSliceConst()) |line_token| { |
| 4354 | 4379 | try stream.print("{}\n", self.tokenizer.getTokenSlice(line_token)); |
| ... | ... | @@ -4430,6 +4455,16 @@ fn testCanonical(source: []const u8) !void { |
| 4430 | 4455 | } |
| 4431 | 4456 | } |
| 4432 | 4457 | |
| 4458 | test "zig fmt: preserve comments before statements" { |
| 4459 | try testCanonical( |
| 4460 | \\test "std" { |
| 4461 | \\ // statement comment |
| 4462 | \\ _ = @import("foo/bar.zig"); |
| 4463 | \\} |
| 4464 | \\ |
| 4465 | ); |
| 4466 | } |
| 4467 | |
| 4433 | 4468 | test "zig fmt: preserve top level comments" { |
| 4434 | 4469 | try testCanonical( |
| 4435 | 4470 | \\// top level comment |