| ... | ... | @@ -55,7 +55,7 @@ pub const Parser = struct { |
| 55 | 55 | visib_token: ?Token, |
| 56 | 56 | extern_export_inline_token: ?Token, |
| 57 | 57 | lib_name: ?&ast.Node, |
| 58 | | comments: ?&ast.Node.LineComment, |
| 58 | comments: ?&ast.Node.DocComment, |
| 59 | 59 | }; |
| 60 | 60 | |
| 61 | 61 | const VarDeclCtx = struct { |
| ... | ... | @@ -65,19 +65,19 @@ pub const Parser = struct { |
| 65 | 65 | extern_export_token: ?Token, |
| 66 | 66 | lib_name: ?&ast.Node, |
| 67 | 67 | list: &ArrayList(&ast.Node), |
| 68 | | comments: ?&ast.Node.LineComment, |
| 68 | comments: ?&ast.Node.DocComment, |
| 69 | 69 | }; |
| 70 | 70 | |
| 71 | 71 | const TopLevelExternOrFieldCtx = struct { |
| 72 | 72 | visib_token: Token, |
| 73 | 73 | container_decl: &ast.Node.ContainerDecl, |
| 74 | | comments: ?&ast.Node.LineComment, |
| 74 | comments: ?&ast.Node.DocComment, |
| 75 | 75 | }; |
| 76 | 76 | |
| 77 | 77 | const ExternTypeCtx = struct { |
| 78 | 78 | opt_ctx: OptionalCtx, |
| 79 | 79 | extern_token: Token, |
| 80 | | comments: ?&ast.Node.LineComment, |
| 80 | comments: ?&ast.Node.DocComment, |
| 81 | 81 | }; |
| 82 | 82 | |
| 83 | 83 | const ContainerKindCtx = struct { |
| ... | ... | @@ -186,7 +186,7 @@ pub const Parser = struct { |
| 186 | 186 | |
| 187 | 187 | const AddCommentsCtx = struct { |
| 188 | 188 | node_ptr: &&ast.Node, |
| 189 | | comments: ?&ast.Node.LineComment, |
| 189 | comments: ?&ast.Node.DocComment, |
| 190 | 190 | }; |
| 191 | 191 | |
| 192 | 192 | const State = union(enum) { |
| ... | ... | @@ -244,8 +244,8 @@ pub const Parser = struct { |
| 244 | 244 | FieldListCommaOrEnd: &ast.Node.ContainerDecl, |
| 245 | 245 | IdentifierListItemOrEnd: ListSave(&ast.Node), |
| 246 | 246 | IdentifierListCommaOrEnd: ListSave(&ast.Node), |
| 247 | | SwitchCaseOrEnd: ListSave(&ast.Node.SwitchCase), |
| 248 | | SwitchCaseCommaOrEnd: ListSave(&ast.Node.SwitchCase), |
| 247 | SwitchCaseOrEnd: ListSave(&ast.Node), |
| 248 | SwitchCaseCommaOrEnd: ListSave(&ast.Node), |
| 249 | 249 | SwitchCaseFirstItem: &ArrayList(&ast.Node), |
| 250 | 250 | SwitchCaseItem: &ArrayList(&ast.Node), |
| 251 | 251 | SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node), |
| ... | ... | @@ -349,6 +349,10 @@ pub const Parser = struct { |
| 349 | 349 | |
| 350 | 350 | switch (state) { |
| 351 | 351 | State.TopLevel => { |
| 352 | while (try self.eatLineComment(arena)) |line_comment| { |
| 353 | try root_node.decls.append(&line_comment.base); |
| 354 | } |
| 355 | |
| 352 | 356 | const comments = try self.eatComments(arena); |
| 353 | 357 | const token = self.getNextToken(); |
| 354 | 358 | switch (token.id) { |
| ... | ... | @@ -358,7 +362,7 @@ pub const Parser = struct { |
| 358 | 362 | const block = try arena.construct(ast.Node.Block { |
| 359 | 363 | .base = ast.Node { |
| 360 | 364 | .id = ast.Node.Id.Block, |
| 361 | | .before_comments = null, |
| 365 | .doc_comments = null, |
| 362 | 366 | .same_line_comment = null, |
| 363 | 367 | }, |
| 364 | 368 | .label = null, |
| ... | ... | @@ -369,7 +373,7 @@ pub const Parser = struct { |
| 369 | 373 | const test_node = try arena.construct(ast.Node.TestDecl { |
| 370 | 374 | .base = ast.Node { |
| 371 | 375 | .id = ast.Node.Id.TestDecl, |
| 372 | | .before_comments = comments, |
| 376 | .doc_comments = comments, |
| 373 | 377 | .same_line_comment = null, |
| 374 | 378 | }, |
| 375 | 379 | .test_token = token, |
| ... | ... | @@ -551,7 +555,7 @@ pub const Parser = struct { |
| 551 | 555 | const fn_proto = try arena.construct(ast.Node.FnProto { |
| 552 | 556 | .base = ast.Node { |
| 553 | 557 | .id = ast.Node.Id.FnProto, |
| 554 | | .before_comments = ctx.comments, |
| 558 | .doc_comments = ctx.comments, |
| 555 | 559 | .same_line_comment = null, |
| 556 | 560 | }, |
| 557 | 561 | .visib_token = ctx.visib_token, |
| ... | ... | @@ -620,7 +624,7 @@ pub const Parser = struct { |
| 620 | 624 | const node = try arena.construct(ast.Node.StructField { |
| 621 | 625 | .base = ast.Node { |
| 622 | 626 | .id = ast.Node.Id.StructField, |
| 623 | | .before_comments = null, |
| 627 | .doc_comments = null, |
| 624 | 628 | .same_line_comment = null, |
| 625 | 629 | }, |
| 626 | 630 | .visib_token = ctx.visib_token, |
| ... | ... | @@ -706,6 +710,10 @@ pub const Parser = struct { |
| 706 | 710 | continue; |
| 707 | 711 | }, |
| 708 | 712 | State.ContainerDecl => |container_decl| { |
| 713 | while (try self.eatLineComment(arena)) |line_comment| { |
| 714 | try container_decl.fields_and_decls.append(&line_comment.base); |
| 715 | } |
| 716 | |
| 709 | 717 | const comments = try self.eatComments(arena); |
| 710 | 718 | const token = self.getNextToken(); |
| 711 | 719 | switch (token.id) { |
| ... | ... | @@ -715,7 +723,7 @@ pub const Parser = struct { |
| 715 | 723 | const node = try arena.construct(ast.Node.StructField { |
| 716 | 724 | .base = ast.Node { |
| 717 | 725 | .id = ast.Node.Id.StructField, |
| 718 | | .before_comments = comments, |
| 726 | .doc_comments = comments, |
| 719 | 727 | .same_line_comment = null, |
| 720 | 728 | }, |
| 721 | 729 | .visib_token = null, |
| ... | ... | @@ -826,7 +834,7 @@ pub const Parser = struct { |
| 826 | 834 | const var_decl = try arena.construct(ast.Node.VarDecl { |
| 827 | 835 | .base = ast.Node { |
| 828 | 836 | .id = ast.Node.Id.VarDecl, |
| 829 | | .before_comments = ctx.comments, |
| 837 | .doc_comments = ctx.comments, |
| 830 | 838 | .same_line_comment = null, |
| 831 | 839 | }, |
| 832 | 840 | .visib_token = ctx.visib_token, |
| ... | ... | @@ -1222,6 +1230,14 @@ pub const Parser = struct { |
| 1222 | 1230 | else => { |
| 1223 | 1231 | self.putBackToken(token); |
| 1224 | 1232 | stack.append(State { .Block = block }) catch unreachable; |
| 1233 | |
| 1234 | var any_comments = false; |
| 1235 | while (try self.eatLineComment(arena)) |line_comment| { |
| 1236 | try block.statements.append(&line_comment.base); |
| 1237 | any_comments = true; |
| 1238 | } |
| 1239 | if (any_comments) continue; |
| 1240 | |
| 1225 | 1241 | try stack.append(State { .Statement = block }); |
| 1226 | 1242 | continue; |
| 1227 | 1243 | }, |
| ... | ... | @@ -1258,7 +1274,7 @@ pub const Parser = struct { |
| 1258 | 1274 | const node = try arena.construct(ast.Node.Defer { |
| 1259 | 1275 | .base = ast.Node { |
| 1260 | 1276 | .id = ast.Node.Id.Defer, |
| 1261 | | .before_comments = comments, |
| 1277 | .doc_comments = comments, |
| 1262 | 1278 | .same_line_comment = null, |
| 1263 | 1279 | }, |
| 1264 | 1280 | .defer_token = token, |
| ... | ... | @@ -1342,7 +1358,7 @@ pub const Parser = struct { |
| 1342 | 1358 | |
| 1343 | 1359 | State.AddComments => |add_comments_ctx| { |
| 1344 | 1360 | const node = *add_comments_ctx.node_ptr; |
| 1345 | | node.before_comments = add_comments_ctx.comments; |
| 1361 | node.doc_comments = add_comments_ctx.comments; |
| 1346 | 1362 | continue; |
| 1347 | 1363 | }, |
| 1348 | 1364 | |
| ... | ... | @@ -1466,7 +1482,7 @@ pub const Parser = struct { |
| 1466 | 1482 | const node = try arena.construct(ast.Node.FieldInitializer { |
| 1467 | 1483 | .base = ast.Node { |
| 1468 | 1484 | .id = ast.Node.Id.FieldInitializer, |
| 1469 | | .before_comments = null, |
| 1485 | .doc_comments = null, |
| 1470 | 1486 | .same_line_comment = null, |
| 1471 | 1487 | }, |
| 1472 | 1488 | .period_token = undefined, |
| ... | ... | @@ -1512,6 +1528,10 @@ pub const Parser = struct { |
| 1512 | 1528 | continue; |
| 1513 | 1529 | }, |
| 1514 | 1530 | State.IdentifierListItemOrEnd => |list_state| { |
| 1531 | while (try self.eatLineComment(arena)) |line_comment| { |
| 1532 | try list_state.list.append(&line_comment.base); |
| 1533 | } |
| 1534 | |
| 1515 | 1535 | if (self.eatToken(Token.Id.RBrace)) |rbrace| { |
| 1516 | 1536 | *list_state.ptr = rbrace; |
| 1517 | 1537 | continue; |
| ... | ... | @@ -1538,6 +1558,10 @@ pub const Parser = struct { |
| 1538 | 1558 | } |
| 1539 | 1559 | }, |
| 1540 | 1560 | State.SwitchCaseOrEnd => |list_state| { |
| 1561 | while (try self.eatLineComment(arena)) |line_comment| { |
| 1562 | try list_state.list.append(&line_comment.base); |
| 1563 | } |
| 1564 | |
| 1541 | 1565 | if (self.eatToken(Token.Id.RBrace)) |rbrace| { |
| 1542 | 1566 | *list_state.ptr = rbrace; |
| 1543 | 1567 | continue; |
| ... | ... | @@ -1547,14 +1571,14 @@ pub const Parser = struct { |
| 1547 | 1571 | const node = try arena.construct(ast.Node.SwitchCase { |
| 1548 | 1572 | .base = ast.Node { |
| 1549 | 1573 | .id = ast.Node.Id.SwitchCase, |
| 1550 | | .before_comments = comments, |
| 1574 | .doc_comments = comments, |
| 1551 | 1575 | .same_line_comment = null, |
| 1552 | 1576 | }, |
| 1553 | 1577 | .items = ArrayList(&ast.Node).init(arena), |
| 1554 | 1578 | .payload = null, |
| 1555 | 1579 | .expr = undefined, |
| 1556 | 1580 | }); |
| 1557 | | try list_state.list.append(node); |
| 1581 | try list_state.list.append(&node.base); |
| 1558 | 1582 | try stack.append(State { .SwitchCaseCommaOrEnd = list_state }); |
| 1559 | 1583 | try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .Required = &node.expr } }); |
| 1560 | 1584 | try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } }); |
| ... | ... | @@ -1569,8 +1593,8 @@ pub const Parser = struct { |
| 1569 | 1593 | continue; |
| 1570 | 1594 | } |
| 1571 | 1595 | |
| 1572 | | const switch_case = list_state.list.toSlice()[list_state.list.len - 1]; |
| 1573 | | try self.lookForSameLineComment(arena, &switch_case.base); |
| 1596 | const node = list_state.list.toSlice()[list_state.list.len - 1]; |
| 1597 | try self.lookForSameLineComment(arena, node); |
| 1574 | 1598 | try stack.append(State { .SwitchCaseOrEnd = list_state }); |
| 1575 | 1599 | continue; |
| 1576 | 1600 | }, |
| ... | ... | @@ -1660,7 +1684,7 @@ pub const Parser = struct { |
| 1660 | 1684 | const fn_proto = try arena.construct(ast.Node.FnProto { |
| 1661 | 1685 | .base = ast.Node { |
| 1662 | 1686 | .id = ast.Node.Id.FnProto, |
| 1663 | | .before_comments = ctx.comments, |
| 1687 | .doc_comments = ctx.comments, |
| 1664 | 1688 | .same_line_comment = null, |
| 1665 | 1689 | }, |
| 1666 | 1690 | .visib_token = null, |
| ... | ... | @@ -2632,7 +2656,7 @@ pub const Parser = struct { |
| 2632 | 2656 | const fn_proto = try arena.construct(ast.Node.FnProto { |
| 2633 | 2657 | .base = ast.Node { |
| 2634 | 2658 | .id = ast.Node.Id.FnProto, |
| 2635 | | .before_comments = null, |
| 2659 | .doc_comments = null, |
| 2636 | 2660 | .same_line_comment = null, |
| 2637 | 2661 | }, |
| 2638 | 2662 | .visib_token = null, |
| ... | ... | @@ -2656,7 +2680,7 @@ pub const Parser = struct { |
| 2656 | 2680 | const fn_proto = try arena.construct(ast.Node.FnProto { |
| 2657 | 2681 | .base = ast.Node { |
| 2658 | 2682 | .id = ast.Node.Id.FnProto, |
| 2659 | | .before_comments = null, |
| 2683 | .doc_comments = null, |
| 2660 | 2684 | .same_line_comment = null, |
| 2661 | 2685 | }, |
| 2662 | 2686 | .visib_token = null, |
| ... | ... | @@ -2749,7 +2773,7 @@ pub const Parser = struct { |
| 2749 | 2773 | const node = try arena.construct(ast.Node.ErrorSetDecl { |
| 2750 | 2774 | .base = ast.Node { |
| 2751 | 2775 | .id = ast.Node.Id.ErrorSetDecl, |
| 2752 | | .before_comments = null, |
| 2776 | .doc_comments = null, |
| 2753 | 2777 | .same_line_comment = null, |
| 2754 | 2778 | }, |
| 2755 | 2779 | .error_token = ctx.error_token, |
| ... | ... | @@ -2829,18 +2853,18 @@ pub const Parser = struct { |
| 2829 | 2853 | } |
| 2830 | 2854 | } |
| 2831 | 2855 | |
| 2832 | | fn eatComments(self: &Parser, arena: &mem.Allocator) !?&ast.Node.LineComment { |
| 2833 | | var result: ?&ast.Node.LineComment = null; |
| 2856 | fn eatComments(self: &Parser, arena: &mem.Allocator) !?&ast.Node.DocComment { |
| 2857 | var result: ?&ast.Node.DocComment = null; |
| 2834 | 2858 | while (true) { |
| 2835 | | if (self.eatToken(Token.Id.LineComment)) |line_comment| { |
| 2859 | if (self.eatToken(Token.Id.DocComment)) |line_comment| { |
| 2836 | 2860 | const node = blk: { |
| 2837 | 2861 | if (result) |comment_node| { |
| 2838 | 2862 | break :blk comment_node; |
| 2839 | 2863 | } else { |
| 2840 | | const comment_node = try arena.construct(ast.Node.LineComment { |
| 2864 | const comment_node = try arena.construct(ast.Node.DocComment { |
| 2841 | 2865 | .base = ast.Node { |
| 2842 | | .id = ast.Node.Id.LineComment, |
| 2843 | | .before_comments = null, |
| 2866 | .id = ast.Node.Id.DocComment, |
| 2867 | .doc_comments = null, |
| 2844 | 2868 | .same_line_comment = null, |
| 2845 | 2869 | }, |
| 2846 | 2870 | .lines = ArrayList(Token).init(arena), |
| ... | ... | @@ -2857,6 +2881,18 @@ pub const Parser = struct { |
| 2857 | 2881 | return result; |
| 2858 | 2882 | } |
| 2859 | 2883 | |
| 2884 | fn eatLineComment(self: &Parser, arena: &mem.Allocator) !?&ast.Node.LineComment { |
| 2885 | const token = self.eatToken(Token.Id.LineComment) ?? return null; |
| 2886 | return try arena.construct(ast.Node.LineComment { |
| 2887 | .base = ast.Node { |
| 2888 | .id = ast.Node.Id.LineComment, |
| 2889 | .doc_comments = null, |
| 2890 | .same_line_comment = null, |
| 2891 | }, |
| 2892 | .token = token, |
| 2893 | }); |
| 2894 | } |
| 2895 | |
| 2860 | 2896 | fn requireSemiColon(node: &const ast.Node) bool { |
| 2861 | 2897 | var n = node; |
| 2862 | 2898 | while (true) { |
| ... | ... | @@ -2874,6 +2910,7 @@ pub const Parser = struct { |
| 2874 | 2910 | ast.Node.Id.SwitchCase, |
| 2875 | 2911 | ast.Node.Id.SwitchElse, |
| 2876 | 2912 | ast.Node.Id.FieldInitializer, |
| 2913 | ast.Node.Id.DocComment, |
| 2877 | 2914 | ast.Node.Id.LineComment, |
| 2878 | 2915 | ast.Node.Id.TestDecl => return false, |
| 2879 | 2916 | ast.Node.Id.While => { |
| ... | ... | @@ -2933,7 +2970,7 @@ pub const Parser = struct { |
| 2933 | 2970 | const node_last_token = node.lastToken(); |
| 2934 | 2971 | |
| 2935 | 2972 | const line_comment_token = self.getNextToken(); |
| 2936 | | if (line_comment_token.id != Token.Id.LineComment) { |
| 2973 | if (line_comment_token.id != Token.Id.DocComment and line_comment_token.id != Token.Id.LineComment) { |
| 2937 | 2974 | self.putBackToken(line_comment_token); |
| 2938 | 2975 | return; |
| 2939 | 2976 | } |
| ... | ... | @@ -3038,18 +3075,21 @@ pub const Parser = struct { |
| 3038 | 3075 | return true; |
| 3039 | 3076 | }, |
| 3040 | 3077 | Token.Id.Keyword_switch => { |
| 3041 | | const node = try self.createToCtxNode(arena, ctx, ast.Node.Switch, |
| 3042 | | ast.Node.Switch { |
| 3043 | | .base = undefined, |
| 3044 | | .switch_token = *token, |
| 3045 | | .expr = undefined, |
| 3046 | | .cases = ArrayList(&ast.Node.SwitchCase).init(arena), |
| 3047 | | .rbrace = undefined, |
| 3048 | | } |
| 3049 | | ); |
| 3078 | const node = try arena.construct(ast.Node.Switch { |
| 3079 | .base = ast.Node { |
| 3080 | .id = ast.Node.Id.Switch, |
| 3081 | .doc_comments = null, |
| 3082 | .same_line_comment = null, |
| 3083 | }, |
| 3084 | .switch_token = *token, |
| 3085 | .expr = undefined, |
| 3086 | .cases = ArrayList(&ast.Node).init(arena), |
| 3087 | .rbrace = undefined, |
| 3088 | }); |
| 3089 | ctx.store(&node.base); |
| 3050 | 3090 | |
| 3051 | 3091 | stack.append(State { |
| 3052 | | .SwitchCaseOrEnd = ListSave(&ast.Node.SwitchCase) { |
| 3092 | .SwitchCaseOrEnd = ListSave(&ast.Node) { |
| 3053 | 3093 | .list = &node.cases, |
| 3054 | 3094 | .ptr = &node.rbrace, |
| 3055 | 3095 | }, |
| ... | ... | @@ -3208,7 +3248,7 @@ pub const Parser = struct { |
| 3208 | 3248 | const id = ast.Node.typeToId(T); |
| 3209 | 3249 | break :blk ast.Node { |
| 3210 | 3250 | .id = id, |
| 3211 | | .before_comments = null, |
| 3251 | .doc_comments = null, |
| 3212 | 3252 | .same_line_comment = null, |
| 3213 | 3253 | }; |
| 3214 | 3254 | }; |
| ... | ... | @@ -3454,6 +3494,10 @@ pub const Parser = struct { |
| 3454 | 3494 | } |
| 3455 | 3495 | try stack.append(RenderState { .Expression = decl }); |
| 3456 | 3496 | }, |
| 3497 | ast.Node.Id.LineComment => { |
| 3498 | const line_comment_node = @fieldParentPtr(ast.Node.LineComment, "base", decl); |
| 3499 | try stream.write(self.tokenizer.getTokenSlice(line_comment_node.token)); |
| 3500 | }, |
| 3457 | 3501 | else => unreachable, |
| 3458 | 3502 | } |
| 3459 | 3503 | }, |
| ... | ... | @@ -3987,7 +4031,9 @@ pub const Parser = struct { |
| 3987 | 4031 | while (i != 0) { |
| 3988 | 4032 | i -= 1; |
| 3989 | 4033 | const node = decls[i]; |
| 3990 | | try stack.append(RenderState { .Text = "," }); |
| 4034 | if (node.id != ast.Node.Id.LineComment) { |
| 4035 | try stack.append(RenderState { .Text = "," }); |
| 4036 | } |
| 3991 | 4037 | try stack.append(RenderState { .Expression = node }); |
| 3992 | 4038 | try stack.append(RenderState { .PrintComments = node }); |
| 3993 | 4039 | try stack.append(RenderState.PrintIndent); |
| ... | ... | @@ -4100,7 +4146,11 @@ pub const Parser = struct { |
| 4100 | 4146 | try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(visib_token) }); |
| 4101 | 4147 | } |
| 4102 | 4148 | }, |
| 4103 | | ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"), |
| 4149 | ast.Node.Id.LineComment => { |
| 4150 | const line_comment_node = @fieldParentPtr(ast.Node.LineComment, "base", base); |
| 4151 | try stream.write(self.tokenizer.getTokenSlice(line_comment_node.token)); |
| 4152 | }, |
| 4153 | ast.Node.Id.DocComment => unreachable, // doc comments are attached to nodes |
| 4104 | 4154 | ast.Node.Id.Switch => { |
| 4105 | 4155 | const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base); |
| 4106 | 4156 | try stream.print("{} (", self.tokenizer.getTokenSlice(switch_node.switch_token)); |
| ... | ... | @@ -4115,7 +4165,7 @@ pub const Parser = struct { |
| 4115 | 4165 | while (i != 0) { |
| 4116 | 4166 | i -= 1; |
| 4117 | 4167 | const node = cases[i]; |
| 4118 | | try stack.append(RenderState { .Expression = &node.base}); |
| 4168 | try stack.append(RenderState { .Expression = node}); |
| 4119 | 4169 | try stack.append(RenderState.PrintIndent); |
| 4120 | 4170 | try stack.append(RenderState { |
| 4121 | 4171 | .Text = blk: { |
| ... | ... | @@ -4487,7 +4537,7 @@ pub const Parser = struct { |
| 4487 | 4537 | } |
| 4488 | 4538 | |
| 4489 | 4539 | fn renderComments(self: &Parser, stream: var, node: &ast.Node, indent: usize) !void { |
| 4490 | | const comment = node.before_comments ?? return; |
| 4540 | const comment = node.doc_comments ?? return; |
| 4491 | 4541 | for (comment.lines.toSliceConst()) |line_token| { |
| 4492 | 4542 | try stream.print("{}\n", self.tokenizer.getTokenSlice(line_token)); |
| 4493 | 4543 | try stream.writeByteNTimes(' ', indent); |