dot-shorthand and more
This commit is contained in:
@@ -742,6 +742,7 @@ pub const Parser = struct {
|
||||
var field_defaults = std.ArrayList(?*Node).empty;
|
||||
var using_entries = std.ArrayList(ast.UsingEntry).empty;
|
||||
var methods = std.ArrayList(*Node).empty;
|
||||
var constants = std.ArrayList(*Node).empty;
|
||||
|
||||
while (self.current.tag != .r_brace and self.current.tag != .eof) {
|
||||
// Check for #using directive
|
||||
@@ -769,17 +770,26 @@ pub const Parser = struct {
|
||||
if (self.current.tag == .l_paren and self.isFunctionDef()) {
|
||||
try methods.append(self.allocator, try self.parseFnDecl(method_name, method_start));
|
||||
} else {
|
||||
return self.fail("only function declarations are allowed inside struct bodies");
|
||||
// Non-function constant: name :: value;
|
||||
const value = try self.parseExpr();
|
||||
if (self.current.tag == .semicolon) self.advance();
|
||||
try constants.append(self.allocator, try self.createNode(method_start, .{ .const_decl = .{
|
||||
.name = method_name,
|
||||
.type_annotation = null,
|
||||
.value = value,
|
||||
} }));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse field group: name1, name2, ...: type (= default)?;
|
||||
// Or typed constant: name :Type: value;
|
||||
var group_names = std.ArrayList([]const u8).empty;
|
||||
|
||||
if (self.current.tag != .identifier) {
|
||||
return self.fail("expected field name in struct");
|
||||
}
|
||||
const field_start = self.current.loc.start;
|
||||
try group_names.append(self.allocator, self.tokenSlice(self.current));
|
||||
self.advance();
|
||||
|
||||
@@ -795,6 +805,19 @@ pub const Parser = struct {
|
||||
try self.expect(.colon);
|
||||
const field_type = try self.parseTypeExpr();
|
||||
|
||||
// Typed constant: name :Type: value; (second colon after type)
|
||||
if (self.current.tag == .colon and group_names.items.len == 1) {
|
||||
self.advance(); // skip second ':'
|
||||
const value = try self.parseExpr();
|
||||
if (self.current.tag == .semicolon) self.advance();
|
||||
try constants.append(self.allocator, try self.createNode(field_start, .{ .const_decl = .{
|
||||
.name = group_names.items[0],
|
||||
.type_annotation = field_type,
|
||||
.value = value,
|
||||
} }));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for default value: = expr
|
||||
var default_val: ?*Node = null;
|
||||
if (self.current.tag == .equal) {
|
||||
@@ -828,6 +851,7 @@ pub const Parser = struct {
|
||||
.type_params = try type_params.toOwnedSlice(self.allocator),
|
||||
.using_entries = try using_entries.toOwnedSlice(self.allocator),
|
||||
.methods = try methods.toOwnedSlice(self.allocator),
|
||||
.constants = try constants.toOwnedSlice(self.allocator),
|
||||
} });
|
||||
}
|
||||
|
||||
@@ -1441,7 +1465,7 @@ pub const Parser = struct {
|
||||
// Null coalescing: expr ?? default
|
||||
if (self.current.tag == .question_question and Prec.null_coalesce >= min_prec) {
|
||||
self.advance();
|
||||
const rhs = try self.parseBinary(Prec.null_coalesce + 1);
|
||||
const rhs = try self.parseBinary(Prec.null_coalesce);
|
||||
lhs = try self.createNode(lhs.span.start, .{ .null_coalesce = .{ .lhs = lhs, .rhs = rhs } });
|
||||
continue;
|
||||
}
|
||||
@@ -1760,16 +1784,7 @@ pub const Parser = struct {
|
||||
}
|
||||
const name = self.tokenSlice(self.current);
|
||||
self.advance();
|
||||
// Enum literal with payload: .variant(payload) — tagged enum (formerly union literal)
|
||||
if (self.current.tag == .l_paren) {
|
||||
self.advance(); // skip '('
|
||||
const payload = try self.parseExpr();
|
||||
try self.expect(.r_paren);
|
||||
return try self.createNode(start, .{ .enum_literal = .{
|
||||
.name = name,
|
||||
.payload = payload,
|
||||
} });
|
||||
}
|
||||
// Enum literal: .variant_name — parsePostfix handles optional (...) as a call
|
||||
return try self.createNode(start, .{ .enum_literal = .{ .name = name } });
|
||||
},
|
||||
.l_paren => {
|
||||
|
||||
Reference in New Issue
Block a user