| ... | @@ -86,9 +86,10 @@ pub const ExpectedContext = enum { | ... | @@ -86,9 +86,10 @@ pub const ExpectedContext = enum { |
| 86 | statement, | 86 | statement, |
| 87 | expression, | 87 | expression, |
| 88 | else_clause, | 88 | else_clause, |
| | 89 | enum_field, |
| 89 | struct_field, | 90 | struct_field, |
| 90 | param_list, | | |
| 91 | static_field, | 91 | static_field, |
| | 92 | param_list, |
| 92 | | 93 | |
| 93 | pub fn description(tag: ExpectedContext) []const u8 { | 94 | pub fn description(tag: ExpectedContext) []const u8 { |
| 94 | return switch (tag) { | 95 | return switch (tag) { |
| ... | @@ -99,6 +100,7 @@ pub const ExpectedContext = enum { | ... | @@ -99,6 +100,7 @@ pub const ExpectedContext = enum { |
| 99 | .expression => "an expression", | 100 | .expression => "an expression", |
| 100 | .else_clause => "an else clause", | 101 | .else_clause => "an else clause", |
| 101 | .struct_field => "a field definition", | 102 | .struct_field => "a field definition", |
| | 103 | .enum_field => "an enum field", |
| 102 | .static_field => "a field name or number", | 104 | .static_field => "a field name or number", |
| 103 | }; | 105 | }; |
| 104 | } | 106 | } |
| ... | @@ -415,7 +417,8 @@ fn parseModuleMembers(p: *Parse) Error!SubList { | ... | @@ -415,7 +417,8 @@ fn parseModuleMembers(p: *Parse) Error!SubList { |
| 415 | => try p.scratch.append(p.gpa, try p.parseModuleDecl()), | 417 | => try p.scratch.append(p.gpa, try p.parseModuleDecl()), |
| 416 | | 418 | |
| 417 | .kw_struct => try p.scratch.append(p.gpa, try p.parseStructDecl(.declaration)), | 419 | .kw_struct => try p.scratch.append(p.gpa, try p.parseStructDecl(.declaration)), |
| 418 | .kw_tuple => try p.scratch.append(p.gpa, try p.parseStructDecl(.declaration)), | 420 | .kw_tuple => try p.scratch.append(p.gpa, try p.parseTupleDecl(.declaration)), |
| | 421 | .kw_enum => try p.scratch.append(p.gpa, try p.parseEnumDecl(.declaration)), |
| 419 | | 422 | |
| 420 | .id => if (p.isContextualKeyword("test")) { | 423 | .id => if (p.isContextualKeyword("test")) { |
| 421 | try p.scratch.append(p.gpa, try p.parseTestDecl()); | 424 | try p.scratch.append(p.gpa, try p.parseTestDecl()); |
| ... | @@ -423,7 +426,6 @@ fn parseModuleMembers(p: *Parse) Error!SubList { | ... | @@ -423,7 +426,6 @@ fn parseModuleMembers(p: *Parse) Error!SubList { |
| 423 | try p.parseExpressionStatement(); | 426 | try p.parseExpressionStatement(); |
| 424 | }, | 427 | }, |
| 425 | | 428 | |
| 426 | .kw_enum, | | |
| 427 | .kw_trait, | 429 | .kw_trait, |
| 428 | .kw_impl, | 430 | .kw_impl, |
| 429 | => |tag| std.debug.panic("TODO: parse {s}", .{@tagName(tag)}), | 431 | => |tag| std.debug.panic("TODO: parse {s}", .{@tagName(tag)}), |
| ... | @@ -608,6 +610,28 @@ fn parseTupleDecl(p: *Parse, ctx: ExprParseContext) Error!NodeIndex { | ... | @@ -608,6 +610,28 @@ fn parseTupleDecl(p: *Parse, ctx: ExprParseContext) Error!NodeIndex { |
| 608 | }); | 610 | }); |
| 609 | } | 611 | } |
| 610 | | 612 | |
| | 613 | fn parseEnumDecl(p: *Parse, ctx: ExprParseContext) Error!NodeIndex { |
| | 614 | const trace = t.trace(@src()); |
| | 615 | defer trace.end(); |
| | 616 | |
| | 617 | const main_token = p.assertToken(.kw_enum); |
| | 618 | |
| | 619 | switch (ctx) { |
| | 620 | .declaration => _ = try p.expect(.id), |
| | 621 | else => {}, |
| | 622 | } |
| | 623 | |
| | 624 | _ = try p.expect(.start_brace); |
| | 625 | |
| | 626 | const fields = try p.parseEnumFieldList(); |
| | 627 | |
| | 628 | return try p.addNode(.{ |
| | 629 | .tag = .@"enum", |
| | 630 | .main_token = main_token, |
| | 631 | .data = .{ .list = fields }, |
| | 632 | }); |
| | 633 | } |
| | 634 | |
| 611 | fn parseTestDecl(p: *Parse) Error!NodeIndex { | 635 | fn parseTestDecl(p: *Parse) Error!NodeIndex { |
| 612 | const trace = t.trace(@src()); | 636 | const trace = t.trace(@src()); |
| 613 | defer trace.end(); | 637 | defer trace.end(); |
| ... | @@ -657,6 +681,33 @@ fn parseStructFieldList(p: *Parse) Error!SubList { | ... | @@ -657,6 +681,33 @@ fn parseStructFieldList(p: *Parse) Error!SubList { |
| 657 | return p.scratchToSubList(scratch_top); | 681 | return p.scratchToSubList(scratch_top); |
| 658 | } | 682 | } |
| 659 | | 683 | |
| | 684 | fn parseEnumFieldList(p: *Parse) Error!SubList { |
| | 685 | const trace = t.trace(@src()); |
| | 686 | defer trace.end(); |
| | 687 | |
| | 688 | const scratch_top = p.scratch.items.len; |
| | 689 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| | 690 | |
| | 691 | while (true) { |
| | 692 | const trace_param = t.traceFmt(@src(), "Param {d}", .{p.scratch.items.len - scratch_top}); |
| | 693 | defer trace_param.end(); |
| | 694 | |
| | 695 | if (p.currentTag() == .end_brace) break; |
| | 696 | |
| | 697 | try p.scratch.append(p.gpa, try p.parseEnumField()); |
| | 698 | |
| | 699 | switch (p.currentTag()) { |
| | 700 | .comma => _ = p.nextToken(), |
| | 701 | .end_brace => break, |
| | 702 | else => return p.failUnexpectedToken(.enum_field), |
| | 703 | } |
| | 704 | } |
| | 705 | |
| | 706 | _ = p.assertToken(.end_brace); |
| | 707 | |
| | 708 | return p.scratchToSubList(scratch_top); |
| | 709 | } |
| | 710 | |
| 660 | fn parseStructField(p: *Parse) Error!NodeIndex { | 711 | fn parseStructField(p: *Parse) Error!NodeIndex { |
| 661 | const trace = t.trace(@src()); | 712 | const trace = t.trace(@src()); |
| 662 | defer trace.end(); | 713 | defer trace.end(); |
| ... | @@ -674,6 +725,32 @@ fn parseStructField(p: *Parse) Error!NodeIndex { | ... | @@ -674,6 +725,32 @@ fn parseStructField(p: *Parse) Error!NodeIndex { |
| 674 | }); | 725 | }); |
| 675 | } | 726 | } |
| 676 | | 727 | |
| | 728 | fn parseEnumField(p: *Parse) Error!NodeIndex { |
| | 729 | const trace = t.trace(@src()); |
| | 730 | defer trace.end(); |
| | 731 | |
| | 732 | const main_token = try p.expect(.id); |
| | 733 | |
| | 734 | const payload = if (p.eatToken(.colon)) |_| |
| | 735 | try p.parseExpressionOrFail(.expression) |
| | 736 | else |
| | 737 | null; |
| | 738 | |
| | 739 | const value = if (p.eatToken(.equal)) |_| |
| | 740 | try p.parseExpressionOrFail(.expression) |
| | 741 | else |
| | 742 | null; |
| | 743 | |
| | 744 | return try p.addNode(.{ |
| | 745 | .tag = .struct_field, |
| | 746 | .main_token = main_token, |
| | 747 | .data = .{ .enum_field = .{ |
| | 748 | .payload = .init(payload), |
| | 749 | .value = .init(value), |
| | 750 | } }, |
| | 751 | }); |
| | 752 | } |
| | 753 | |
| 677 | fn parseBlock(p: *Parse) Error!NodeIndex { | 754 | fn parseBlock(p: *Parse) Error!NodeIndex { |
| 678 | const trace = t.trace(@src()); | 755 | const trace = t.trace(@src()); |
| 679 | defer trace.end(); | 756 | defer trace.end(); |