...
This commit is contained in:
@@ -408,15 +408,23 @@ pub const Parser = struct {
|
||||
try variant_names.append(self.allocator, self.tokenSlice(self.current));
|
||||
self.advance();
|
||||
if (self.current.tag == .colon_colon) {
|
||||
// Explicit value: name :: expr;
|
||||
if (!is_flags) {
|
||||
return self.fail("explicit enum values require 'enum flags'");
|
||||
}
|
||||
// Explicit value: name :: expr; or name :: expr: type;
|
||||
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;
|
||||
// Check for payload type after value: name :: 0x300: KeyData
|
||||
if (self.current.tag == .colon) {
|
||||
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);
|
||||
has_any_type = true;
|
||||
} else {
|
||||
try variant_types.append(self.allocator, null);
|
||||
}
|
||||
} else if (self.current.tag == .colon) {
|
||||
// Typed variant: name: type;
|
||||
if (is_flags) {
|
||||
@@ -553,7 +561,12 @@ pub const Parser = struct {
|
||||
|
||||
// All names in the group share the same type and default
|
||||
for (group_names.items) |fname| {
|
||||
try field_names.append(self.allocator, fname);
|
||||
// `_` is an ignore identifier — auto-rename to unique internal name
|
||||
const actual_name = if (std.mem.eql(u8, fname, "_"))
|
||||
try std.fmt.allocPrint(self.allocator, "_{d}", .{field_names.items.len})
|
||||
else
|
||||
fname;
|
||||
try field_names.append(self.allocator, actual_name);
|
||||
try field_types.append(self.allocator, field_type);
|
||||
try field_defaults.append(self.allocator, default_val);
|
||||
}
|
||||
@@ -892,6 +905,24 @@ pub const Parser = struct {
|
||||
return try self.createNode(start, .{ .insert_expr = .{ .expr = inner } });
|
||||
}
|
||||
|
||||
// Block-form if/while/for as statements — parse directly to prevent
|
||||
// postfix chaining (e.g. `if cond { ... }.field` being misparsed)
|
||||
if (self.current.tag == .kw_if) {
|
||||
const expr = try self.parseIfExpr();
|
||||
try self.expectSemicolonAfter(expr);
|
||||
return expr;
|
||||
}
|
||||
if (self.current.tag == .kw_while) {
|
||||
const expr = try self.parsePrimary();
|
||||
try self.expectSemicolonAfter(expr);
|
||||
return expr;
|
||||
}
|
||||
if (self.current.tag == .kw_for) {
|
||||
const expr = try self.parsePrimary();
|
||||
try self.expectSemicolonAfter(expr);
|
||||
return expr;
|
||||
}
|
||||
|
||||
// Expression statement
|
||||
const expr = try self.parseExpr();
|
||||
|
||||
@@ -1427,11 +1458,28 @@ pub const Parser = struct {
|
||||
} else try self.parsePrimary(); // .variant
|
||||
try self.expect(.colon);
|
||||
|
||||
// Optional payload capture: (ident)
|
||||
var capture: ?[]const u8 = null;
|
||||
if (self.current.tag == .l_paren) {
|
||||
self.advance();
|
||||
if (self.current.tag != .identifier) return self.fail("expected capture name");
|
||||
capture = self.tokenSlice(self.current);
|
||||
self.advance();
|
||||
try self.expect(.r_paren);
|
||||
}
|
||||
|
||||
if (self.current.tag == .kw_break) {
|
||||
self.advance();
|
||||
try self.expect(.semicolon);
|
||||
const body = try self.createNode(arm_start, .{ .block = .{ .stmts = &.{} } });
|
||||
try arms.append(self.allocator, .{ .pattern = pattern, .body = body, .is_break = true });
|
||||
try arms.append(self.allocator, .{ .pattern = pattern, .body = body, .is_break = true, .capture = capture });
|
||||
} else if (self.current.tag == .fat_arrow) {
|
||||
// Short form: (ident) => expr;
|
||||
self.advance();
|
||||
const expr = try self.parseExpr();
|
||||
try self.expect(.semicolon);
|
||||
const body = try self.createNode(arm_start, .{ .block = .{ .stmts = try self.allocator.dupe(*Node, &.{expr}) } });
|
||||
try arms.append(self.allocator, .{ .pattern = pattern, .body = body, .is_break = false, .capture = capture });
|
||||
} else {
|
||||
const stmts_start = self.current.loc.start;
|
||||
var stmts = std.ArrayList(*Node).empty;
|
||||
@@ -1439,7 +1487,7 @@ pub const Parser = struct {
|
||||
try stmts.append(self.allocator, try self.parseStmt());
|
||||
}
|
||||
const body = try self.createNode(stmts_start, .{ .block = .{ .stmts = try stmts.toOwnedSlice(self.allocator) } });
|
||||
try arms.append(self.allocator, .{ .pattern = pattern, .body = body, .is_break = false });
|
||||
try arms.append(self.allocator, .{ .pattern = pattern, .body = body, .is_break = false, .capture = capture });
|
||||
}
|
||||
}
|
||||
// Optional else arm (default)
|
||||
|
||||
Reference in New Issue
Block a user