begin work on new registry: api constants & tags

This commit is contained in:
Robin Voetter
2020-06-09 03:02:17 +02:00
parent c2974a16e6
commit 47c9bcb8a3
4 changed files with 243 additions and 13 deletions

View File

@@ -1,7 +1,22 @@
const std = @import("std"); const std = @import("std");
const xml = @import("xml.zig"); const xml = @import("xml.zig");
const Registry = @import("registry.zig").Registry; const parseXml = @import("spec-parse.zig").parseXml;
const vk_render = @import("render.zig").render; 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 { pub fn main() !void {
if (std.os.argv.len <= 1) { if (std.os.argv.len <= 1) {
@@ -21,13 +36,10 @@ pub fn main() !void {
const spec = try xml.parse(std.heap.page_allocator, source); const spec = try xml.parse(std.heap.page_allocator, source);
defer spec.deinit(); defer spec.deinit();
const registry = Registry.fromXml(std.heap.page_allocator, spec.root); const result = try parseXml(std.heap.page_allocator, spec.root);
defer registry.deinit(); defer result.deinit();
// registry.dump();
const stdout_file = std.io.getStdOut(); dumpRegistry(result.registry);
var stdout = stdout_file.outStream();
try vk_render(stdout, registry);
} }
test "main" { test "main" {

106
generator/registry-new.zig Normal file
View File

@@ -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,
};

90
generator/spec-parse.zig Normal file
View File

@@ -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);
}

View File

@@ -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 { pub fn findChildByTag(self: *Element, tag: []const u8) ?*Element {
return self.findChildrenByTag(tag).next(); return self.findChildrenByTag(tag).next();
} }
pub fn findChildrenByTag(self: *Element, tag: []const u8) FindChildrenByTagIterator { pub fn findChildrenByTag(self: *Element, tag: []const u8) FindChildrenByTagIterator {
return .{ return .{
.inner = self.children.iterator(0), .inner = self.elements(),
.tag = tag .tag = tag
}; };
} }
pub const FindChildrenByTagIterator = struct { pub const ChildElementIterator = struct {
inner: ContentList.Iterator, inner: ContentList.Iterator,
tag: []const u8,
pub fn next(self: *FindChildrenByTagIterator) ?*Element { pub fn next(self: *ChildElementIterator) ?*Element {
while (self.inner.next()) |child| { while (self.inner.next()) |child| {
if (child.* != .Element or !mem.eql(u8, child.*.Element.tag, self.tag)) { if (child.* != .Element) {
continue; continue;
} }
@@ -82,6 +87,23 @@ pub const Element = struct {
return null; 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 { pub const XmlDecl = struct {