feat(ffi-linkage): add kw_extern/kw_export tokens (Phase 0.0)

Lex 'extern' and 'export' as keywords beside 'callconv': new token.Tag
variants + keywords StaticStringMap entries + LSP semantic-token keyword
classification. Adds a 'lex linkage keywords' unit test.

Tokens only — parser/AST plumbing and lowering land in later phases.
Corpus sweep confirmed no .sx identifier collides with the new reserved
words. lock commit per the cadence rule.
This commit is contained in:
agra
2026-06-14 12:40:35 +03:00
parent 78f7bb7857
commit bf6ef8370f
4 changed files with 32 additions and 6 deletions

View File

@@ -537,6 +537,15 @@ test "lex keywords" {
}
}
test "lex linkage keywords" {
// extern / export are keywords (FFI-linkage stream), lexed beside callconv.
var lex = Lexer.init("callconv extern export");
const expected = [_]Tag{ .kw_callconv, .kw_extern, .kw_export };
for (expected) |exp| {
try std.testing.expectEqual(exp, lex.next().tag);
}
}
test "lex type-like identifiers" {
// i32, u8, bool, string are identifiers, not keywords
var lex = Lexer.init("i32 u8 bool string");

View File

@@ -1683,6 +1683,8 @@ pub const Server = struct {
.kw_impl,
.kw_inline,
.kw_callconv,
.kw_extern,
.kw_export,
.hash_run,
.hash_import,
.hash_insert,

View File

@@ -43,6 +43,8 @@ pub const Tag = enum {
kw_Self, // Self (in protocol declarations)
kw_inline, // inline (compile-time if/for/while)
kw_callconv, // callconv (calling convention annotation)
kw_extern, // extern (import: external linkage, C ABI, no body)
kw_export, // export (define + expose: external linkage, C ABI)
// Symbols
colon, // :
@@ -280,6 +282,8 @@ pub const keywords = std.StaticStringMap(Tag).initComptime(.{
.{ "Self", .kw_Self },
.{ "inline", .kw_inline },
.{ "callconv", .kw_callconv },
.{ "extern", .kw_extern },
.{ "export", .kw_export },
});
pub fn getKeyword(bytes: []const u8) ?Tag {