http server
This commit is contained in:
@@ -62,19 +62,6 @@ pub const Parser = struct {
|
||||
return try self.createNode(start, .{ .import_decl = .{ .path = path, .name = null } });
|
||||
}
|
||||
|
||||
// Top-level #library directive: #library "libname";
|
||||
if (self.current.tag == .hash_library) {
|
||||
self.advance();
|
||||
if (self.current.tag != .string_literal) {
|
||||
return self.fail("expected string after '#library'");
|
||||
}
|
||||
const raw = self.tokenSlice(self.current);
|
||||
const lib_name = raw[1 .. raw.len - 1];
|
||||
self.advance();
|
||||
try self.expect(.semicolon);
|
||||
return try self.createNode(start, .{ .library_decl = .{ .lib_name = lib_name } });
|
||||
}
|
||||
|
||||
// Top-level #run directive
|
||||
if (self.current.tag == .hash_run) {
|
||||
self.advance();
|
||||
@@ -131,6 +118,19 @@ pub const Parser = struct {
|
||||
return try self.createNode(start_pos, .{ .import_decl = .{ .path = path, .name = name } });
|
||||
}
|
||||
|
||||
// Named library: name :: #library "libname";
|
||||
if (self.current.tag == .hash_library) {
|
||||
self.advance();
|
||||
if (self.current.tag != .string_literal) {
|
||||
return self.fail("expected string after '#library'");
|
||||
}
|
||||
const raw = self.tokenSlice(self.current);
|
||||
const lib_name = raw[1 .. raw.len - 1];
|
||||
self.advance();
|
||||
try self.expect(.semicolon);
|
||||
return try self.createNode(start_pos, .{ .library_decl = .{ .lib_name = lib_name, .name = name } });
|
||||
}
|
||||
|
||||
// Compile-time evaluation: name :: #run expr;
|
||||
if (self.current.tag == .hash_run) {
|
||||
const run_start = self.current.loc.start;
|
||||
@@ -192,12 +192,27 @@ pub const Parser = struct {
|
||||
return try self.createNode(start_pos, .{ .const_decl = .{ .name = name, .type_annotation = value, .value = bi } });
|
||||
}
|
||||
|
||||
// name :: type_expr #foreign; — foreign with type annotation
|
||||
// name :: type_expr #foreign lib ["c_name"]; — foreign with type annotation
|
||||
if (self.current.tag == .hash_foreign) {
|
||||
const fi_start = self.current.loc.start;
|
||||
self.advance();
|
||||
// Required: library reference (identifier)
|
||||
if (self.current.tag != .identifier)
|
||||
return self.fail("expected library name after '#foreign'");
|
||||
const lib_ref = self.tokenSlice(self.current);
|
||||
self.advance();
|
||||
// Optional: C symbol name (string literal)
|
||||
var c_name: ?[]const u8 = null;
|
||||
if (self.current.tag == .string_literal) {
|
||||
const raw = self.tokenSlice(self.current);
|
||||
c_name = raw[1 .. raw.len - 1];
|
||||
self.advance();
|
||||
}
|
||||
try self.expect(.semicolon);
|
||||
const fi = try self.createNode(fi_start, .{ .foreign_expr = {} });
|
||||
const fi = try self.createNode(fi_start, .{ .foreign_expr = .{
|
||||
.library_ref = lib_ref,
|
||||
.c_name = c_name,
|
||||
} });
|
||||
return try self.createNode(start_pos, .{ .const_decl = .{ .name = name, .type_annotation = value, .value = fi } });
|
||||
}
|
||||
|
||||
@@ -754,8 +769,23 @@ pub const Parser = struct {
|
||||
} else if (self.current.tag == .hash_foreign) blk: {
|
||||
const fi_start = self.current.loc.start;
|
||||
self.advance();
|
||||
// Required: library reference (identifier)
|
||||
if (self.current.tag != .identifier)
|
||||
return self.fail("expected library name after '#foreign'");
|
||||
const lib_ref = self.tokenSlice(self.current);
|
||||
self.advance();
|
||||
// Optional: C symbol name (string literal)
|
||||
var c_name: ?[]const u8 = null;
|
||||
if (self.current.tag == .string_literal) {
|
||||
const raw = self.tokenSlice(self.current);
|
||||
c_name = raw[1 .. raw.len - 1];
|
||||
self.advance();
|
||||
}
|
||||
try self.expect(.semicolon);
|
||||
break :blk try self.createNode(fi_start, .{ .foreign_expr = {} });
|
||||
break :blk try self.createNode(fi_start, .{ .foreign_expr = .{
|
||||
.library_ref = lib_ref,
|
||||
.c_name = c_name,
|
||||
} });
|
||||
} else if (self.current.tag == .fat_arrow) blk: {
|
||||
is_arrow = true;
|
||||
self.advance();
|
||||
@@ -1826,7 +1856,7 @@ test "parse namespaced import" {
|
||||
}
|
||||
|
||||
test "parse library declaration" {
|
||||
const source = "#library \"raylib\";";
|
||||
const source = "rl :: #library \"raylib\";";
|
||||
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
||||
defer arena.deinit();
|
||||
var parser = Parser.init(arena.allocator(), source);
|
||||
@@ -1835,6 +1865,7 @@ test "parse library declaration" {
|
||||
const decl = root.data.root.decls[0];
|
||||
try std.testing.expect(decl.data == .library_decl);
|
||||
try std.testing.expectEqualStrings("raylib", decl.data.library_decl.lib_name);
|
||||
try std.testing.expectEqualStrings("rl", decl.data.library_decl.name);
|
||||
}
|
||||
|
||||
test "parse void function with builtin body" {
|
||||
@@ -1851,7 +1882,7 @@ test "parse void function with builtin body" {
|
||||
}
|
||||
|
||||
test "parse void function with foreign body" {
|
||||
const source = "InitWindow :: (width: s32, height: s32, title: *u8) -> void #foreign;";
|
||||
const source = "InitWindow :: (width: s32, height: s32, title: *u8) -> void #foreign rl;";
|
||||
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
||||
defer arena.deinit();
|
||||
var parser = Parser.init(arena.allocator(), source);
|
||||
@@ -1861,6 +1892,7 @@ test "parse void function with foreign body" {
|
||||
try std.testing.expect(decl.data == .fn_decl);
|
||||
try std.testing.expectEqualStrings("InitWindow", decl.data.fn_decl.name);
|
||||
try std.testing.expect(decl.data.fn_decl.body.data == .foreign_expr);
|
||||
try std.testing.expectEqualStrings("rl", decl.data.fn_decl.body.data.foreign_expr.library_ref.?);
|
||||
try std.testing.expectEqual(@as(usize, 3), decl.data.fn_decl.params.len);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user