flags
This commit is contained in:
@@ -381,25 +381,50 @@ pub const Parser = struct {
|
||||
|
||||
fn parseEnumDecl(self: *Parser, name: []const u8, start_pos: u32) anyerror!*Node {
|
||||
self.advance(); // skip 'enum'
|
||||
|
||||
// Check for 'flags' modifier: enum flags { ... }
|
||||
var is_flags = false;
|
||||
if (self.current.tag == .identifier and std.mem.eql(u8, self.tokenSlice(self.current), "flags")) {
|
||||
is_flags = true;
|
||||
self.advance();
|
||||
}
|
||||
|
||||
try self.expect(.l_brace);
|
||||
var variant_names = std.ArrayList([]const u8).empty;
|
||||
var variant_types = std.ArrayList(?*Node).empty;
|
||||
var variant_values = std.ArrayList(?*Node).empty;
|
||||
var has_any_type = false;
|
||||
var has_any_value = false;
|
||||
while (self.current.tag != .r_brace and self.current.tag != .eof) {
|
||||
if (self.current.tag != .identifier) {
|
||||
return self.fail("expected variant name");
|
||||
}
|
||||
try variant_names.append(self.allocator, self.tokenSlice(self.current));
|
||||
self.advance();
|
||||
if (self.current.tag == .colon) {
|
||||
if (self.current.tag == .colon_colon) {
|
||||
// Explicit value: name :: expr;
|
||||
if (!is_flags) {
|
||||
return self.fail("explicit enum values require 'enum flags'");
|
||||
}
|
||||
self.advance();
|
||||
const val_expr = try self.parseExpr();
|
||||
try variant_values.append(self.allocator, val_expr);
|
||||
try variant_types.append(self.allocator, null);
|
||||
has_any_value = true;
|
||||
} else if (self.current.tag == .colon) {
|
||||
// Typed variant: name: type;
|
||||
if (is_flags) {
|
||||
return self.fail("flags enum variants cannot have payloads");
|
||||
}
|
||||
self.advance();
|
||||
const vtype = try self.parseTypeExpr();
|
||||
try variant_types.append(self.allocator, vtype);
|
||||
try variant_values.append(self.allocator, null);
|
||||
has_any_type = true;
|
||||
} else {
|
||||
// Void variant: name;
|
||||
try variant_types.append(self.allocator, null);
|
||||
try variant_values.append(self.allocator, null);
|
||||
}
|
||||
if (self.current.tag == .semicolon) {
|
||||
self.advance();
|
||||
@@ -411,6 +436,8 @@ pub const Parser = struct {
|
||||
.name = name,
|
||||
.variant_names = try variant_names.toOwnedSlice(self.allocator),
|
||||
.variant_types = if (has_any_type) try variant_types.toOwnedSlice(self.allocator) else &.{},
|
||||
.is_flags = is_flags,
|
||||
.variant_values = if (has_any_value) try variant_values.toOwnedSlice(self.allocator) else &.{},
|
||||
} });
|
||||
}
|
||||
|
||||
@@ -1539,6 +1566,8 @@ pub const Parser = struct {
|
||||
return switch (self.current.tag) {
|
||||
.kw_or => 1,
|
||||
.kw_and => 2,
|
||||
.pipe => 3,
|
||||
.ampersand => 3,
|
||||
.equal_equal, .bang_equal, .less, .less_equal, .greater, .greater_equal => 4,
|
||||
.plus, .minus => 5,
|
||||
.star, .slash, .percent => 6,
|
||||
@@ -1550,6 +1579,8 @@ pub const Parser = struct {
|
||||
return switch (self.current.tag) {
|
||||
.kw_and => .and_op,
|
||||
.kw_or => .or_op,
|
||||
.pipe => .bit_or,
|
||||
.ampersand => .bit_and,
|
||||
.plus => .add,
|
||||
.minus => .sub,
|
||||
.star => .mul,
|
||||
|
||||
Reference in New Issue
Block a user