This commit is contained in:
agra
2026-02-24 13:37:27 +02:00
parent 170e236764
commit b98711a1d3
13 changed files with 157 additions and 632 deletions

View File

@@ -83,7 +83,7 @@ pub const Parser = struct {
}
// All top-level declarations start with an identifier
if (self.current.tag != .identifier and self.current.tag != .kw_Self) {
if (!self.isIdentLike() and self.current.tag != .kw_Self) {
return self.fail("expected identifier at top level");
}
const name = self.tokenSlice(self.current);
@@ -426,7 +426,7 @@ pub const Parser = struct {
}
// Check for optional param name: `name: Type`
// An identifier followed by `:` (not `::` or `:=`) is a param name
if (self.current.tag == .identifier and self.peekNext() == .colon) {
if (self.isIdentLike() and self.peekNext() == .colon) {
const pname = self.tokenSlice(self.current);
self.advance(); // skip name
self.advance(); // skip ':'
@@ -455,7 +455,7 @@ pub const Parser = struct {
} });
}
if (self.current.tag.isTypeKeyword() or self.current.tag == .identifier) {
if (self.current.tag.isTypeKeyword() or self.isIdentLike()) {
var name = self.tokenSlice(self.current);
self.advance();
@@ -465,7 +465,7 @@ pub const Parser = struct {
const dot_current = self.current;
const dot_prev_end = self.prev_end;
self.advance();
if (self.current.tag == .identifier or self.current.tag.isTypeKeyword()) {
if (self.isIdentLike() or self.current.tag.isTypeKeyword()) {
name = try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ name, self.tokenSlice(self.current) });
self.advance();
} else {
@@ -1065,7 +1065,7 @@ pub const Parser = struct {
is_ct_param = true;
self.advance();
}
if (self.current.tag != .identifier) {
if (!self.isIdentLike()) {
return self.fail("expected parameter name");
}
const param_name = self.tokenSlice(self.current);
@@ -1252,7 +1252,7 @@ pub const Parser = struct {
pub fn parseStmt(self: *Parser) anyerror!*Node {
// Check if this is a declaration (IDENT followed by ::, :=, or : type)
if (self.current.tag == .identifier) {
if (self.isIdentLike()) {
const saved_lexer = self.lexer;
const saved_current = self.current;
const saved_prev_end = self.prev_end;
@@ -1721,10 +1721,11 @@ pub const Parser = struct {
self.advance();
return try self.createNode(start, .{ .identifier = .{ .name = name } });
},
.kw_closure => {
// `closure` keyword used as identifier in expressions (closure intrinsic call)
.kw_closure, .kw_protocol, .kw_impl, .kw_ufcs => {
// Contextual keywords used as identifiers in expressions
const name = self.tokenSlice(self.current);
self.advance();
return try self.createNode(start, .{ .identifier = .{ .name = "closure" } });
return try self.createNode(start, .{ .identifier = .{ .name = name } });
},
.dot => {
self.advance();
@@ -2277,6 +2278,16 @@ pub const Parser = struct {
// ---- Helpers ----
/// Returns true if the current token can be used as an identifier name.
/// Includes actual identifiers plus contextual keywords that are only
/// keywords in specific syntactic positions (e.g., `protocol`, `impl`).
fn isIdentLike(self: *const Parser) bool {
return switch (self.current.tag) {
.identifier, .kw_protocol, .kw_impl, .kw_ufcs, .kw_closure => true,
else => false,
};
}
fn isFunctionDef(self: *Parser) bool {
const tag = self.peekPastParens() orelse return false;
return tag == .l_brace or tag == .arrow or tag == .hash_builtin or tag == .hash_foreign or tag == .fat_arrow;