import c
This commit is contained in:
@@ -49,9 +49,14 @@ pub const Parser = struct {
|
||||
fn parseTopLevel(self: *Parser) anyerror!*Node {
|
||||
const start = self.current.loc.start;
|
||||
|
||||
// Top-level flat import: #import "path";
|
||||
// Top-level flat import: #import "path"; or #import c { ... };
|
||||
if (self.current.tag == .hash_import) {
|
||||
self.advance();
|
||||
// Check for #import c { ... } (C import block)
|
||||
if (self.current.tag == .identifier and std.mem.eql(u8, self.tokenSlice(self.current), "c") and self.peekNext() == .l_brace) {
|
||||
self.advance(); // consume 'c'
|
||||
return self.parseCImportBlock(start, null);
|
||||
}
|
||||
if (self.current.tag != .string_literal) {
|
||||
return self.fail("expected string path after '#import'");
|
||||
}
|
||||
@@ -105,9 +110,14 @@ pub const Parser = struct {
|
||||
// After `::`
|
||||
// Could be: #run expr, enum { ... }, (params) -> type { body }, or expr;
|
||||
|
||||
// Namespaced import: name :: #import "path";
|
||||
// Namespaced import: name :: #import "path"; or name :: #import c { ... };
|
||||
if (self.current.tag == .hash_import) {
|
||||
self.advance();
|
||||
// Check for name :: #import c { ... }
|
||||
if (self.current.tag == .identifier and std.mem.eql(u8, self.tokenSlice(self.current), "c") and self.peekNext() == .l_brace) {
|
||||
self.advance(); // consume 'c'
|
||||
return self.parseCImportBlock(start_pos, name);
|
||||
}
|
||||
if (self.current.tag != .string_literal) {
|
||||
return self.fail("expected string path after '#import'");
|
||||
}
|
||||
@@ -232,6 +242,58 @@ pub const Parser = struct {
|
||||
return try self.createNode(start_pos, .{ .const_decl = .{ .name = name, .type_annotation = null, .value = value } });
|
||||
}
|
||||
|
||||
fn parseCImportBlock(self: *Parser, start: u32, name: ?[]const u8) anyerror!*Node {
|
||||
try self.expect(.l_brace);
|
||||
var includes = std.ArrayList([]const u8).empty;
|
||||
var sources = std.ArrayList([]const u8).empty;
|
||||
var defines = std.ArrayList([]const u8).empty;
|
||||
var flags = std.ArrayList([]const u8).empty;
|
||||
|
||||
while (self.current.tag != .r_brace and self.current.tag != .eof) {
|
||||
if (self.current.tag == .hash_include) {
|
||||
self.advance();
|
||||
if (self.current.tag != .string_literal) return self.fail("expected string after '#include'");
|
||||
const raw = self.tokenSlice(self.current);
|
||||
try includes.append(self.allocator, raw[1 .. raw.len - 1]);
|
||||
self.advance();
|
||||
try self.expect(.semicolon);
|
||||
} else if (self.current.tag == .hash_source) {
|
||||
self.advance();
|
||||
if (self.current.tag != .string_literal) return self.fail("expected string after '#source'");
|
||||
const raw = self.tokenSlice(self.current);
|
||||
try sources.append(self.allocator, raw[1 .. raw.len - 1]);
|
||||
self.advance();
|
||||
try self.expect(.semicolon);
|
||||
} else if (self.current.tag == .hash_define) {
|
||||
self.advance();
|
||||
if (self.current.tag != .string_literal) return self.fail("expected string after '#define'");
|
||||
const raw = self.tokenSlice(self.current);
|
||||
try defines.append(self.allocator, raw[1 .. raw.len - 1]);
|
||||
self.advance();
|
||||
try self.expect(.semicolon);
|
||||
} else if (self.current.tag == .hash_flags) {
|
||||
self.advance();
|
||||
if (self.current.tag != .string_literal) return self.fail("expected string after '#flags'");
|
||||
const raw = self.tokenSlice(self.current);
|
||||
try flags.append(self.allocator, raw[1 .. raw.len - 1]);
|
||||
self.advance();
|
||||
try self.expect(.semicolon);
|
||||
} else {
|
||||
return self.fail("unexpected token inside '#import c { ... }'");
|
||||
}
|
||||
}
|
||||
try self.expect(.r_brace);
|
||||
try self.expect(.semicolon);
|
||||
|
||||
return try self.createNode(start, .{ .c_import_decl = .{
|
||||
.includes = try includes.toOwnedSlice(self.allocator),
|
||||
.sources = try sources.toOwnedSlice(self.allocator),
|
||||
.defines = try defines.toOwnedSlice(self.allocator),
|
||||
.flags = try flags.toOwnedSlice(self.allocator),
|
||||
.name = name,
|
||||
} });
|
||||
}
|
||||
|
||||
fn parseTypedBinding(self: *Parser, name: []const u8, start_pos: u32) anyerror!*Node {
|
||||
// After `name :`
|
||||
// Parse type
|
||||
|
||||
Reference in New Issue
Block a user