| ... | ... | @@ -18,6 +18,7 @@ pub const Parser = struct { |
| 18 | 18 | put_back_tokens: [2]Token, |
| 19 | 19 | put_back_count: usize, |
| 20 | 20 | source_file_name: []const u8, |
| 21 | pending_line_comment_node: ?&ast.NodeLineComment, |
| 21 | 22 | |
| 22 | 23 | pub const Tree = struct { |
| 23 | 24 | root_node: &ast.NodeRoot, |
| ... | ... | @@ -43,6 +44,7 @@ pub const Parser = struct { |
| 43 | 44 | .put_back_count = 0, |
| 44 | 45 | .source_file_name = source_file_name, |
| 45 | 46 | .utility_bytes = []align(utility_bytes_align) u8{}, |
| 47 | .pending_line_comment_node = null, |
| 46 | 48 | }; |
| 47 | 49 | } |
| 48 | 50 | |
| ... | ... | @@ -131,6 +133,33 @@ pub const Parser = struct { |
| 131 | 133 | // warn("\n"); |
| 132 | 134 | //} |
| 133 | 135 | |
| 136 | // look for line comments |
| 137 | while (true) { |
| 138 | const token = self.getNextToken(); |
| 139 | if (token.id == Token.Id.LineComment) { |
| 140 | const node = blk: { |
| 141 | if (self.pending_line_comment_node) |comment_node| { |
| 142 | break :blk comment_node; |
| 143 | } else { |
| 144 | const comment_node = try arena.create(ast.NodeLineComment); |
| 145 | *comment_node = ast.NodeLineComment { |
| 146 | .base = ast.Node { |
| 147 | .id = ast.Node.Id.LineComment, |
| 148 | .comment = null, |
| 149 | }, |
| 150 | .lines = ArrayList(Token).init(arena), |
| 151 | }; |
| 152 | self.pending_line_comment_node = comment_node; |
| 153 | break :blk comment_node; |
| 154 | } |
| 155 | }; |
| 156 | try node.lines.append(token); |
| 157 | continue; |
| 158 | } |
| 159 | self.putBackToken(token); |
| 160 | break; |
| 161 | } |
| 162 | |
| 134 | 163 | // This gives us 1 free append that can't fail |
| 135 | 164 | const state = stack.pop(); |
| 136 | 165 | |
| ... | ... | @@ -329,7 +358,7 @@ pub const Parser = struct { |
| 329 | 358 | Token.Id.Builtin => { |
| 330 | 359 | const node = try arena.create(ast.NodeBuiltinCall); |
| 331 | 360 | *node = ast.NodeBuiltinCall { |
| 332 | | .base = ast.Node {.id = ast.Node.Id.BuiltinCall}, |
| 361 | .base = self.initNode(ast.Node.Id.BuiltinCall), |
| 333 | 362 | .builtin_token = token, |
| 334 | 363 | .params = ArrayList(&ast.Node).init(arena), |
| 335 | 364 | .rparen_token = undefined, |
| ... | ... | @@ -350,7 +379,7 @@ pub const Parser = struct { |
| 350 | 379 | Token.Id.StringLiteral => { |
| 351 | 380 | const node = try arena.create(ast.NodeStringLiteral); |
| 352 | 381 | *node = ast.NodeStringLiteral { |
| 353 | | .base = ast.Node {.id = ast.Node.Id.StringLiteral}, |
| 382 | .base = self.initNode(ast.Node.Id.StringLiteral), |
| 354 | 383 | .token = token, |
| 355 | 384 | }; |
| 356 | 385 | try stack.append(State { |
| ... | ... | @@ -359,6 +388,7 @@ pub const Parser = struct { |
| 359 | 388 | try stack.append(State.AfterOperand); |
| 360 | 389 | continue; |
| 361 | 390 | }, |
| 391 | |
| 362 | 392 | else => return self.parseError(token, "expected primary expression, found {}", @tagName(token.id)), |
| 363 | 393 | } |
| 364 | 394 | }, |
| ... | ... | @@ -660,11 +690,19 @@ pub const Parser = struct { |
| 660 | 690 | } |
| 661 | 691 | } |
| 662 | 692 | |
| 693 | fn initNode(self: &Parser, id: ast.Node.Id) ast.Node { |
| 694 | if (self.pending_line_comment_node) |comment_node| { |
| 695 | self.pending_line_comment_node = null; |
| 696 | return ast.Node {.id = id, .comment = comment_node}; |
| 697 | } |
| 698 | return ast.Node {.id = id, .comment = null }; |
| 699 | } |
| 700 | |
| 663 | 701 | fn createRoot(self: &Parser, arena: &mem.Allocator) !&ast.NodeRoot { |
| 664 | 702 | const node = try arena.create(ast.NodeRoot); |
| 665 | 703 | |
| 666 | 704 | *node = ast.NodeRoot { |
| 667 | | .base = ast.Node {.id = ast.Node.Id.Root}, |
| 705 | .base = self.initNode(ast.Node.Id.Root), |
| 668 | 706 | .decls = ArrayList(&ast.Node).init(arena), |
| 669 | 707 | // initialized when we get the eof token |
| 670 | 708 | .eof_token = undefined, |
| ... | ... | @@ -678,7 +716,7 @@ pub const Parser = struct { |
| 678 | 716 | const node = try arena.create(ast.NodeVarDecl); |
| 679 | 717 | |
| 680 | 718 | *node = ast.NodeVarDecl { |
| 681 | | .base = ast.Node {.id = ast.Node.Id.VarDecl}, |
| 719 | .base = self.initNode(ast.Node.Id.VarDecl), |
| 682 | 720 | .visib_token = *visib_token, |
| 683 | 721 | .mut_token = *mut_token, |
| 684 | 722 | .comptime_token = *comptime_token, |
| ... | ... | @@ -701,7 +739,7 @@ pub const Parser = struct { |
| 701 | 739 | const node = try arena.create(ast.NodeFnProto); |
| 702 | 740 | |
| 703 | 741 | *node = ast.NodeFnProto { |
| 704 | | .base = ast.Node {.id = ast.Node.Id.FnProto}, |
| 742 | .base = self.initNode(ast.Node.Id.FnProto), |
| 705 | 743 | .visib_token = *visib_token, |
| 706 | 744 | .name_token = null, |
| 707 | 745 | .fn_token = *fn_token, |
| ... | ... | @@ -722,7 +760,7 @@ pub const Parser = struct { |
| 722 | 760 | const node = try arena.create(ast.NodeParamDecl); |
| 723 | 761 | |
| 724 | 762 | *node = ast.NodeParamDecl { |
| 725 | | .base = ast.Node {.id = ast.Node.Id.ParamDecl}, |
| 763 | .base = self.initNode(ast.Node.Id.ParamDecl), |
| 726 | 764 | .comptime_token = null, |
| 727 | 765 | .noalias_token = null, |
| 728 | 766 | .name_token = null, |
| ... | ... | @@ -736,7 +774,7 @@ pub const Parser = struct { |
| 736 | 774 | const node = try arena.create(ast.NodeBlock); |
| 737 | 775 | |
| 738 | 776 | *node = ast.NodeBlock { |
| 739 | | .base = ast.Node {.id = ast.Node.Id.Block}, |
| 777 | .base = self.initNode(ast.Node.Id.Block), |
| 740 | 778 | .begin_token = *begin_token, |
| 741 | 779 | .end_token = undefined, |
| 742 | 780 | .statements = ArrayList(&ast.Node).init(arena), |
| ... | ... | @@ -748,7 +786,7 @@ pub const Parser = struct { |
| 748 | 786 | const node = try arena.create(ast.NodeInfixOp); |
| 749 | 787 | |
| 750 | 788 | *node = ast.NodeInfixOp { |
| 751 | | .base = ast.Node {.id = ast.Node.Id.InfixOp}, |
| 789 | .base = self.initNode(ast.Node.Id.InfixOp), |
| 752 | 790 | .op_token = *op_token, |
| 753 | 791 | .lhs = undefined, |
| 754 | 792 | .op = *op, |
| ... | ... | @@ -761,7 +799,7 @@ pub const Parser = struct { |
| 761 | 799 | const node = try arena.create(ast.NodePrefixOp); |
| 762 | 800 | |
| 763 | 801 | *node = ast.NodePrefixOp { |
| 764 | | .base = ast.Node {.id = ast.Node.Id.PrefixOp}, |
| 802 | .base = self.initNode(ast.Node.Id.PrefixOp), |
| 765 | 803 | .op_token = *op_token, |
| 766 | 804 | .op = *op, |
| 767 | 805 | .rhs = undefined, |
| ... | ... | @@ -773,7 +811,7 @@ pub const Parser = struct { |
| 773 | 811 | const node = try arena.create(ast.NodeIdentifier); |
| 774 | 812 | |
| 775 | 813 | *node = ast.NodeIdentifier { |
| 776 | | .base = ast.Node {.id = ast.Node.Id.Identifier}, |
| 814 | .base = self.initNode(ast.Node.Id.Identifier), |
| 777 | 815 | .name_token = *name_token, |
| 778 | 816 | }; |
| 779 | 817 | return node; |
| ... | ... | @@ -783,7 +821,7 @@ pub const Parser = struct { |
| 783 | 821 | const node = try arena.create(ast.NodeIntegerLiteral); |
| 784 | 822 | |
| 785 | 823 | *node = ast.NodeIntegerLiteral { |
| 786 | | .base = ast.Node {.id = ast.Node.Id.IntegerLiteral}, |
| 824 | .base = self.initNode(ast.Node.Id.IntegerLiteral), |
| 787 | 825 | .token = *token, |
| 788 | 826 | }; |
| 789 | 827 | return node; |
| ... | ... | @@ -793,7 +831,7 @@ pub const Parser = struct { |
| 793 | 831 | const node = try arena.create(ast.NodeFloatLiteral); |
| 794 | 832 | |
| 795 | 833 | *node = ast.NodeFloatLiteral { |
| 796 | | .base = ast.Node {.id = ast.Node.Id.FloatLiteral}, |
| 834 | .base = self.initNode(ast.Node.Id.FloatLiteral), |
| 797 | 835 | .token = *token, |
| 798 | 836 | }; |
| 799 | 837 | return node; |
| ... | ... | @@ -1158,9 +1196,11 @@ pub const Parser = struct { |
| 1158 | 1196 | } |
| 1159 | 1197 | } |
| 1160 | 1198 | }, |
| 1199 | ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"), |
| 1200 | ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"), |
| 1201 | |
| 1161 | 1202 | ast.Node.Id.Root, |
| 1162 | 1203 | ast.Node.Id.VarDecl, |
| 1163 | | ast.Node.Id.FnProto, |
| 1164 | 1204 | ast.Node.Id.ParamDecl => unreachable, |
| 1165 | 1205 | }, |
| 1166 | 1206 | RenderState.FnProtoRParen => |fn_proto| { |
| ... | ... | @@ -1187,6 +1227,12 @@ pub const Parser = struct { |
| 1187 | 1227 | } |
| 1188 | 1228 | }, |
| 1189 | 1229 | RenderState.Statement => |base| { |
| 1230 | if (base.comment) |comment| { |
| 1231 | for (comment.lines.toSliceConst()) |line_token| { |
| 1232 | try stream.print("{}\n", self.tokenizer.getTokenSlice(line_token)); |
| 1233 | try stream.writeByteNTimes(' ', indent); |
| 1234 | } |
| 1235 | } |
| 1190 | 1236 | switch (base.id) { |
| 1191 | 1237 | ast.Node.Id.VarDecl => { |
| 1192 | 1238 | const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", base); |
| ... | ... | @@ -1279,6 +1325,17 @@ fn testCanonical(source: []const u8) !void { |
| 1279 | 1325 | } |
| 1280 | 1326 | |
| 1281 | 1327 | test "zig fmt" { |
| 1328 | try testCanonical( |
| 1329 | \\const std = @import("std"); |
| 1330 | \\ |
| 1331 | \\pub fn main() !void { |
| 1332 | \\ // If this program is run without stdout attached, exit with an error. |
| 1333 | \\ // another comment |
| 1334 | \\ var stdout_file = try std.io.getStdOut; |
| 1335 | \\} |
| 1336 | \\ |
| 1337 | ); |
| 1338 | |
| 1282 | 1339 | try testCanonical( |
| 1283 | 1340 | \\const std = @import("std"); |
| 1284 | 1341 | \\ |