diff --git a/generator/main.zig b/generator/main.zig index d42699b..122214d 100644 --- a/generator/main.zig +++ b/generator/main.zig @@ -1,7 +1,22 @@ const std = @import("std"); const xml = @import("xml.zig"); -const Registry = @import("registry.zig").Registry; -const vk_render = @import("render.zig").render; +const parseXml = @import("spec-parse.zig").parseXml; +const registry = @import("registry-new.zig"); + +pub fn dumpRegistry(reg: registry.Registry) void { + for (reg.tags) |tag| { + std.debug.warn("tag: name = {}, author = {}\n", .{tag.name, tag.author}); + } + + for (reg.api_constants) |api_constant| { + std.debug.warn("constant: name = {}, ", .{api_constant.name}); + switch (api_constant.value) { + .expr => |expr| std.debug.warn("expr = {}\n", .{expr}), + .alias => |alias| std.debug.warn("alias = {}\n", .{alias}), + } + + } +} pub fn main() !void { if (std.os.argv.len <= 1) { @@ -21,13 +36,10 @@ pub fn main() !void { const spec = try xml.parse(std.heap.page_allocator, source); defer spec.deinit(); - const registry = Registry.fromXml(std.heap.page_allocator, spec.root); - defer registry.deinit(); - // registry.dump(); + const result = try parseXml(std.heap.page_allocator, spec.root); + defer result.deinit(); - const stdout_file = std.io.getStdOut(); - var stdout = stdout_file.outStream(); - try vk_render(stdout, registry); + dumpRegistry(result.registry); } test "main" { diff --git a/generator/registry-new.zig b/generator/registry-new.zig new file mode 100644 index 0000000..8113eda --- /dev/null +++ b/generator/registry-new.zig @@ -0,0 +1,106 @@ +pub const Registry = struct { + decls: []Declaration, + api_constants: []ApiConstant, + tags: []Tag, +}; + +pub const Declaration = struct { + name: []const u8, + decl_type: TypeInfo, +}; + +pub const ApiConstant = struct { + pub const Value = union(enum) { + expr: []const u8, + alias: []const u8, + }; + + name: []const u8, + value: Value, +}; + +pub const Tag = struct { + name: []const u8, + author: []const u8, +}; + +pub const TypeInfo = union(enum) { + Struct: Container, + Union: Container, + Enum: Enum, + Bitmask: Bitmask, + Handle: Handle, + FnPtr: Command, + Command: Command, + Alias: []const u8, + Pointer: Pointer, + Array: Array, + Opaque: void, +}; + +pub const Container = struct { + pub const Field = struct { + name: []const u8, + field_type: TypeInfo, + }; + + fields: []Field, +}; + +pub const Enum = struct { + pub const Value = union(enum) { + bitpos: u5, // 1 << bitpos + bitvector: u32, // Combined flags + int: i32, + alias: []const u8, + }; + + pub const Field = struct { + name: []const u8, + value: Value, + }; + + fields: []Field, + is_bitmask_bits: bool, +}; + +pub const Bitmask = struct { + bits_enum: ?[]const u8, +}; + +pub const Handle = struct { + is_dispatchable: bool, +}; + +pub const Command = struct { + const Param = struct { + name: []const u8, + param_type: TypeInfo, + }; + + params: []Param, + return_type: *TypeInfo, + success_codes: []const []const u8, + error_codes: []const []const u8, +}; + +pub const Pointer = struct { + pub const PointerSize = enum { + one, + many, // The length is given by some expression + zero_terminated + }; + + is_const: bool, + child: *TypeInfo, +}; + +pub const Array = struct { + pub const ArraySize = union(enum) { + int: usize, + alias: []const u8, // Field size is given by an api constant + }; + + size: ArraySize, + child: *TypeInfo, +}; diff --git a/generator/spec-parse.zig b/generator/spec-parse.zig new file mode 100644 index 0000000..710b4d6 --- /dev/null +++ b/generator/spec-parse.zig @@ -0,0 +1,90 @@ +const std = @import("std"); +const registry = @import("registry-new.zig"); +const xml = @import("xml.zig"); +const mem = std.mem; +const Allocator = mem.Allocator; +const ArenaAllocator = std.heap.ArenaAllocator; + +pub const ParseResult = struct { + arena: ArenaAllocator, + registry: registry.Registry, + + pub fn deinit(self: ParseResult) void { + self.arena.deinit(); + } +}; + +pub fn parseXml(allocator: *Allocator, root: *xml.Element) !ParseResult { + var arena = ArenaAllocator.init(allocator); + errdefer arena.deinit(); + + var reg = registry.Registry{ + .decls = &[_]registry.Declaration{}, + .api_constants = &[_]registry.ApiConstant{}, + .tags = &[_]registry.Tag{}, + }; + + reg.api_constants = try parseApiConstants(&arena.allocator, root); + reg.tags = try parseTags(&arena.allocator, root); + + return ParseResult{ + .arena = arena, + .registry = reg, + }; +} + +fn parseApiConstants(allocator: *Allocator, root: *xml.Element) ![]registry.ApiConstant { + var enums = blk: { + var it = root.elements(); + while (it.next()) |child| { + const name = child.getAttribute("name") orelse continue; + if (mem.eql(u8, name, "API Constants")) { + break :blk child; + } + } + + return error.InvalidRegistry; + }; + + var constants = try allocator.alloc(registry.ApiConstant, enums.children.count()); + errdefer allocator.free(constants); + + var i: usize = 0; + var it = enums.findChildrenByTag("enum"); + while (it.next()) |constant| { + const value = if (constant.getAttribute("value")) |expr| + registry.ApiConstant.Value{.expr = expr} + else if (constant.getAttribute("alias")) |alias| + registry.ApiConstant.Value{.alias = alias} + else + return error.InvalidRegistry; + + constants[i] = .{ + .name = constant.getAttribute("name") orelse return error.InvalidRegistry, + .value = value, + }; + + i += 1; + } + + return allocator.shrink(constants, i); +} + +fn parseTags(allocator: *Allocator, root: *xml.Element) ![]registry.Tag { + var tags_elem = root.findChildByTag("tags") orelse return error.InvalidRegistry; + var tags = try allocator.alloc(registry.Tag, tags_elem.children.count()); + errdefer allocator.free(tags); + + var i: usize = 0; + var it = tags_elem.findChildrenByTag("tag"); + while (it.next()) |tag| { + tags[i] = .{ + .name = tag.getAttribute("name") orelse return error.InvalidRegistry, + .author = tag.getAttribute("author") orelse return error.InvalidRegistry, + }; + + i += 1; + } + + return allocator.shrink(tags, i); +} diff --git a/generator/xml.zig b/generator/xml.zig index 9debba6..6b9870d 100644 --- a/generator/xml.zig +++ b/generator/xml.zig @@ -55,24 +55,29 @@ pub const Element = struct { }; } + pub fn elements(self: *Element) ChildElementIterator { + return .{ + .inner = self.children.iterator(0), + }; + } + pub fn findChildByTag(self: *Element, tag: []const u8) ?*Element { return self.findChildrenByTag(tag).next(); } pub fn findChildrenByTag(self: *Element, tag: []const u8) FindChildrenByTagIterator { return .{ - .inner = self.children.iterator(0), + .inner = self.elements(), .tag = tag }; } - pub const FindChildrenByTagIterator = struct { + pub const ChildElementIterator = struct { inner: ContentList.Iterator, - tag: []const u8, - pub fn next(self: *FindChildrenByTagIterator) ?*Element { + pub fn next(self: *ChildElementIterator) ?*Element { while (self.inner.next()) |child| { - if (child.* != .Element or !mem.eql(u8, child.*.Element.tag, self.tag)) { + if (child.* != .Element) { continue; } @@ -82,6 +87,23 @@ pub const Element = struct { return null; } }; + + pub const FindChildrenByTagIterator = struct { + inner: ChildElementIterator, + tag: []const u8, + + pub fn next(self: *FindChildrenByTagIterator) ?*Element { + while (self.inner.next()) |child| { + if (!mem.eql(u8, child.tag, self.tag)) { + continue; + } + + return child; + } + + return null; + } + }; }; pub const XmlDecl = struct {