authorchloe caruso <git@paperclover.net> 2024-10-29 00:07:51-07:00
committerchloe caruso <git@paperclover.net> 2024-10-29 00:07:51-07:00
logb1f64e4c22560b8bf8cfa321d28ea21308dfb957
tree0c4f0fa4b44c7552543f9046fc5385d1e577048c
parent2bcfa5e47db1ba080d7add7d2cd7a59e0e249bd1
signature Commit is signed but in an unrecognized format.

feat: parse enums


5 files changed, 137 insertions(+), 3 deletions(-)

CHANGELOG.md+2
......@@ -1,5 +1,7 @@
11## 0.1.8
22
3- feat: implement basic enum types
4
35## 0.1.7
46
57- news: rename the language to "ix"
src/core/Ast.Dump.zig+15
......@@ -177,6 +177,21 @@ fn dumpNode(writer: anytype, state: *State, node: NodeIndex) @TypeOf(writer).Err
177177 try dumpNode(writer, state, ty);
178178 }
179179 },
180 .enum_field => {
181 try writer.writeAll(" ");
182 const enum_field = state.ast.fullEnumField(node);
183 try tty.setColor(writer, .magenta);
184 try writer.writeAll(enum_field.id);
185 try tty.setColor(writer, .reset);
186 if (enum_field.payload) |ty| {
187 try writer.writeAll(": ");
188 try dumpNode(writer, state, ty);
189 }
190 if (enum_field.value) |ty| {
191 try writer.writeAll(" = ");
192 try dumpNode(writer, state, ty);
193 }
194 },
180195 .bin => {
181196 try writer.writeAll(" (");
182197 {
src/core/Ast.zig+35
......@@ -215,6 +215,12 @@ pub const Node = struct {
215215 struct_field,
216216 /// Struct Init
217217 struct_init,
218 /// Enum Declaration
219 @"enum",
220 /// Enum Field
221 enum_field,
222 /// Enum Literal
223 enum_literal,
218224 /// Array type
219225 array_type,
220226 /// Array initialization
......@@ -336,6 +342,9 @@ pub const Node = struct {
336342 .shl_assign = .bin,
337343 .shr = .bin,
338344 .shr_assign = .bin,
345 .@"enum" = .list,
346 .enum_literal = .none,
347 .enum_field = .none,
339348 .string = .none,
340349 .struct_decl = .list,
341350 .array_type = .un,
......@@ -371,6 +380,10 @@ pub const Node = struct {
371380 type: OptionalNodeIndex,
372381 unused: Unused = .zero,
373382 },
383 enum_field: struct {
384 payload: OptionalNodeIndex,
385 value: OptionalNodeIndex,
386 },
374387 bin: struct {
375388 lhs: NodeIndex,
376389 rhs: NodeIndex,
......@@ -566,6 +579,13 @@ pub const full = struct {
566579 id: []const u8,
567580 type: ?NodeIndex,
568581 };
582
583 pub const EnumField = struct {
584 start_token: TokenIndex,
585 id: []const u8,
586 payload: ?NodeIndex,
587 value: ?NodeIndex,
588 };
569589};
570590
571591pub fn deinit(ast: *Ast, gpa: std.mem.Allocator) void {
......@@ -691,6 +711,21 @@ pub fn fullParamDecl(ast: Ast, node: NodeIndex) full.ParamDecl {
691711 };
692712}
693713
714pub fn fullEnumField(ast: Ast, node: NodeIndex) full.EnumField {
715 const tok_tags = ast.tokens.items(.tag);
716
717 const main_token = ast.nodes.items(.main_token)[node];
718 assert(tok_tags[main_token] == .id);
719 const id = ast.tokenSlice(main_token);
720 const data = ast.nodes.items(.data)[node].enum_field;
721 return .{
722 .start_token = main_token,
723 .id = id,
724 .payload = data.payload.unwrap(),
725 .value = data.value.unwrap(),
726 };
727}
728
694729pub fn fullStructField(ast: Ast, node: NodeIndex) full.StructField {
695730 const tok_tags = ast.tokens.items(.tag);
696731
src/core/Parse.zig+80-3
......@@ -86,9 +86,10 @@ pub const ExpectedContext = enum {
8686 statement,
8787 expression,
8888 else_clause,
89 enum_field,
8990 struct_field,
90 param_list,
9191 static_field,
92 param_list,
9293
9394 pub fn description(tag: ExpectedContext) []const u8 {
9495 return switch (tag) {
......@@ -99,6 +100,7 @@ pub const ExpectedContext = enum {
99100 .expression => "an expression",
100101 .else_clause => "an else clause",
101102 .struct_field => "a field definition",
103 .enum_field => "an enum field",
102104 .static_field => "a field name or number",
103105 };
104106 }
......@@ -415,7 +417,8 @@ fn parseModuleMembers(p: *Parse) Error!SubList {
415417 => try p.scratch.append(p.gpa, try p.parseModuleDecl()),
416418
417419 .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)),
419422
420423 .id => if (p.isContextualKeyword("test")) {
421424 try p.scratch.append(p.gpa, try p.parseTestDecl());
......@@ -423,7 +426,6 @@ fn parseModuleMembers(p: *Parse) Error!SubList {
423426 try p.parseExpressionStatement();
424427 },
425428
426 .kw_enum,
427429 .kw_trait,
428430 .kw_impl,
429431 => |tag| std.debug.panic("TODO: parse {s}", .{@tagName(tag)}),
......@@ -608,6 +610,28 @@ fn parseTupleDecl(p: *Parse, ctx: ExprParseContext) Error!NodeIndex {
608610 });
609611}
610612
613fn 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
611635fn parseTestDecl(p: *Parse) Error!NodeIndex {
612636 const trace = t.trace(@src());
613637 defer trace.end();
......@@ -657,6 +681,33 @@ fn parseStructFieldList(p: *Parse) Error!SubList {
657681 return p.scratchToSubList(scratch_top);
658682}
659683
684fn 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
660711fn parseStructField(p: *Parse) Error!NodeIndex {
661712 const trace = t.trace(@src());
662713 defer trace.end();
......@@ -674,6 +725,32 @@ fn parseStructField(p: *Parse) Error!NodeIndex {
674725 });
675726}
676727
728fn 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
677754fn parseBlock(p: *Parse) Error!NodeIndex {
678755 const trace = t.trace(@src());
679756 defer trace.end();
test/behavior/enum.ix created+5
......@@ -0,0 +1,5 @@
1enum Mode {
2 first,
3 second,
4 @"enum",
5}