Backlog/lib/cimgui/generator/generator.zig

174 lines
4.3 KiB
Zig

const std = @import("std");
pub const log_level: std.log.Level = .debug;
const ProgramOptions = struct {
outputFile: ?[]u8 = null,
inputFile: ?[]u8 = null,
allocator: std.mem.Allocator,
pub fn deinit(self: @This()) void {
if (self.outputFile) |f| {
self.allocator.free(f);
}
if (self.inputFile) |f| {
self.allocator.free(f);
}
}
fn matchArgOpt(arg: []const u8, long: []const u8, short: ?[]const u8) bool {
if (arg.len < 2) {
return false;
}
if (arg[0] == '-') {
if (arg[1] == '-') {
return std.mem.eql(u8, arg[2..], long);
} else if (short) |s| {
return arg[1] == s[0];
}
}
return false;
}
pub fn parseArgs(allocator: std.mem.Allocator) !@This() {
var rv: @This() = .{ .allocator = allocator };
const args = try std.process.argsAlloc(allocator);
defer std.process.argsFree(allocator, args);
var i: usize = 0;
while (i < args.len) : (i += 1) {
if (i <= 0) {
continue;
}
if (matchArgOpt(args[i], "input", "i")) {
i += 1;
rv.inputFile = try allocator.dupe(u8, args[i]);
} else if (matchArgOpt(args[i], "output", "o")) {
i += 1;
rv.outputFile = try allocator.dupe(u8, args[i]);
}
}
if (rv.outputFile == null) {
rv.outputFile = try allocator.dupe(u8, "imgui.zig");
}
return rv;
}
};
// Parses out all of the cimgui functions and sorts them by calling type.
const ParserContext = struct {
arena: std.heap.ArenaAllocator,
backingAllocator: std.mem.Allocator,
opts: *const ProgramOptions,
read: []const u8 = undefined,
buffer: []const u8 = undefined,
state: enum {
Empty,
Label,
Struct,
Function,
} = .Empty,
pub fn create(allocator: std.mem.Allocator, options: *const ProgramOptions) !*@This() {
const self = try allocator.create(@This());
self.* = .{
.backingAllocator = allocator,
.arena = std.heap.ArenaAllocator.init(allocator),
.opts = options,
};
return self;
}
const ParseResults = struct {};
pub fn getAllocator(self: *@This()) std.mem.Allocator {
return self.arena.allocator();
}
fn matchString(self: *@This(), str: []const u8) ?usize {
if (self.read.len < str.len) {
return null;
}
if (std.mem.eql(u8, self.read[0..str.len], str)) {
return str.len - 1;
}
return null;
}
fn advanceEmpty(self: *@This()) !void {
if (self.matchString("struct")) |len| {
std.log.info("STRUCT FOUND! {s}", .{self.read[0 .. len + 1]});
self.advance(len);
}
}
inline fn next(self: *@This()) !void {
switch (self.state) {
.Empty => {
try self.advanceEmpty();
},
.Label => {},
.Struct => {},
.Function => {},
}
self.advance(1);
}
inline fn advance(self: *@This(), count: usize) void {
self.read = self.read[count..];
}
pub fn parseHeader(self: *@This()) !ParseResults {
var file = try std.fs.cwd().openFile(self.opts.inputFile.?, .{});
defer file.close();
self.buffer = try file.reader().readAllAlloc(self.getAllocator(), 1 * 1024 * 1024 * 1024);
self.read = self.buffer;
while (self.read.len > 0) {
try self.next();
}
return .{};
}
pub fn destroy(self: *@This()) void {
self.arena.deinit();
self.backingAllocator.destroy(self);
}
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const opts = try ProgramOptions.parseArgs(allocator);
defer opts.deinit();
std.log.info("inputFile={?s}, outputFile={?s}", .{
opts.inputFile,
opts.outputFile,
});
const tokenizer = try Tokenizer.create(allocator, &opts);
defer tokenizer.destroy();
const tokenizeResults = try tokenizer.tokenize();
}