ffi 2.7 green: parser accepts all seven type-introducer directive forms
Six new lexer tokens (`hash_jni_interface`, `hash_objc_class`, `hash_objc_protocol`, `hash_swift_class`, `hash_swift_struct`, `hash_swift_protocol`) join the existing `hash_jni_class`. All seven share the body grammar from Phases 2.1–2.6. AST refactored: `JniClassDecl` → `ForeignClassDecl` with a `runtime: ForeignRuntime` enum discriminator; `JniMethodDecl` → `ForeignMethodDecl` (with `jni_descriptor_override` renamed for clarity since it's JNI-only); `JniFieldDecl` → `ForeignFieldDecl`; `JniClassMember` → `ForeignClassMember`. AST variant renamed `jni_class_decl` → `foreign_class_decl`. `parseForeignClassDecl` takes the runtime as a parameter; the `parseConstBinding` dispatch table now maps each of the seven directive tokens to its `ForeignRuntime` variant via `foreignRuntimeForCurrent`. No codegen yet — Phase 3 picks up Obj-C runtime, Phase 4 picks up Swift. Runtime-specific body items (fields, descriptor override) are validated at sema time in later steps. 126/126 examples green.
This commit is contained in:
@@ -209,9 +209,10 @@ pub const Parser = struct {
|
||||
return self.parseProtocolDecl(name, start_pos);
|
||||
}
|
||||
|
||||
// JNI class binding: name :: #jni_class("java/path/Foo") { ...body... }
|
||||
if (self.current.tag == .hash_jni_class) {
|
||||
return self.parseJniClassDecl(name, start_pos);
|
||||
// Foreign-type binding: name :: #jni_class / #jni_interface / #objc_class /
|
||||
// #objc_protocol / #swift_class / #swift_struct / #swift_protocol ("path") { body }
|
||||
if (self.foreignRuntimeForCurrent()) |runtime| {
|
||||
return self.parseForeignClassDecl(name, start_pos, runtime);
|
||||
}
|
||||
|
||||
// C-style union declaration
|
||||
@@ -1027,21 +1028,34 @@ pub const Parser = struct {
|
||||
} });
|
||||
}
|
||||
|
||||
fn parseJniClassDecl(self: *Parser, name: []const u8, start_pos: u32) anyerror!*Node {
|
||||
self.advance(); // skip '#jni_class'
|
||||
fn foreignRuntimeForCurrent(self: *Parser) ?ast.ForeignRuntime {
|
||||
return switch (self.current.tag) {
|
||||
.hash_jni_class => .jni_class,
|
||||
.hash_jni_interface => .jni_interface,
|
||||
.hash_objc_class => .objc_class,
|
||||
.hash_objc_protocol => .objc_protocol,
|
||||
.hash_swift_class => .swift_class,
|
||||
.hash_swift_struct => .swift_struct,
|
||||
.hash_swift_protocol => .swift_protocol,
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
|
||||
fn parseForeignClassDecl(self: *Parser, name: []const u8, start_pos: u32, runtime: ast.ForeignRuntime) anyerror!*Node {
|
||||
self.advance(); // skip directive token
|
||||
|
||||
try self.expect(.l_paren);
|
||||
if (self.current.tag != .string_literal) {
|
||||
return self.fail("expected string literal Java class path after '#jni_class('");
|
||||
return self.fail("expected string literal foreign-type path after directive");
|
||||
}
|
||||
const raw = self.tokenSlice(self.current);
|
||||
const java_path = raw[1 .. raw.len - 1];
|
||||
const foreign_path = raw[1 .. raw.len - 1];
|
||||
self.advance();
|
||||
try self.expect(.r_paren);
|
||||
|
||||
try self.expect(.l_brace);
|
||||
|
||||
var members = std.ArrayList(ast.JniClassMember).empty;
|
||||
var members = std.ArrayList(ast.ForeignClassMember).empty;
|
||||
while (self.current.tag != .r_brace and self.current.tag != .eof) {
|
||||
// #extends Alias; or #implements Alias;
|
||||
if (self.current.tag == .hash_extends or self.current.tag == .hash_implements) {
|
||||
@@ -1143,14 +1157,15 @@ pub const Parser = struct {
|
||||
.param_names = try param_names.toOwnedSlice(self.allocator),
|
||||
.return_type = return_type,
|
||||
.is_static = is_static,
|
||||
.desc_override = desc_override,
|
||||
.jni_descriptor_override = desc_override,
|
||||
} });
|
||||
}
|
||||
try self.expect(.r_brace);
|
||||
|
||||
return try self.createNode(start_pos, .{ .jni_class_decl = .{
|
||||
return try self.createNode(start_pos, .{ .foreign_class_decl = .{
|
||||
.name = name,
|
||||
.java_path = java_path,
|
||||
.foreign_path = foreign_path,
|
||||
.runtime = runtime,
|
||||
.members = try members.toOwnedSlice(self.allocator),
|
||||
} });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user