sdlparser-scrap/AGENTS.md

91 lines
3.2 KiB
Markdown

# SDL3 Header Parser - Agent Documentation
## Project Overview
This is an SDL3 header parser that converts C header files into Zig interfaces, JSON objects, and C mocks. Built specifically for SDL3 headers (developed against SDL 3.2.10), it focuses on generating Zig APIs.
**Key Points:**
- Not a real C parser - best-effort text transformation specifically for SDL3 headers
- Does not do proper AST elaboration or tokenization
- Simple to modify but brittle
- Requires Zig 0.15.2 and git
## Architecture
The codebase consists of several modules:
- `parser.zig` - Main entry point and orchestration
- `patterns.zig` - SDL3 pattern matching and declaration scanning
- `codegen.zig` - Zig code generation
- `mock_codegen.zig` - C mock generation
- `json_serializer.zig` - JSON output generation
- `dependency_resolver.zig` - Type dependency resolution
- `header_cache.zig` - Header caching for cross-file type resolution
- `io.zig` - Error handling utilities
- `types.zig` - Type mapping and conversions
- `naming.zig` - Naming conventions
## Developing
### Build System Patterns
**Custom Build Steps:**
The project uses custom Zig build steps for operations that need to happen during the build process:
```zig
const MakeDirStep = struct {
step: std.Build.Step,
dir_path: []const u8,
pub fn create(b: *std.Build, dir_path: []const u8) *std.Build.Step {
const self = b.allocator.create(MakeDirStep) catch @panic("OOM");
self.* = .{
.step = std.Build.Step.init(.{
.id = .custom,
.name = b.fmt("mkdir {s}", .{dir_path}),
.owner = b,
.makeFn = make,
}),
.dir_path = dir_path,
};
return &self.step;
}
fn make(step: *std.Build.Step, options: std.Build.Step.MakeOptions) !void {
_ = options;
const self: *MakeDirStep = @fieldParentPtr("step", step);
try std.fs.cwd().makePath(self.dir_path);
}
};
```
This pattern allows cross-platform directory creation and other filesystem operations during build without relying on shell commands.
### Error Handling
**CRITICAL:** Whenever actual errors are encountered (parsing failures, invalid declarations, missing types, etc.), you MUST call `io.emitError` to report them properly. Do NOT use `std.debug.print` for actual errors.
```zig
// Good - proper error reporting
try io.emitError(allocator, "Failed to parse struct field: {s}", .{field_name});
// Bad - don't use for errors
std.debug.print("Error: Failed to parse...\n", .{});
```
### Validation Process
After generating Zig code:
1. Output written to `tmp/` directory
2. `zig ast-check` runs on the temporary file
3. If passes: `zig fmt` runs, then copied to final destination
4. If fails: debug output written to `debug/` with `_fmterror.zig` suffix
### Memory Management
- Two cleanup functions exist with identical logic:
- `freeDecls()` - frees a slice of declarations
- `freeDeclDeep()` - frees a single declaration
- Both free all nested allocations (names, types, doc comments, params/fields/values/flags)
### Main APIs (Priority)
Focus areas: gpu, video, gamepad, joystick, input, event
Anything beyond these is not actively maintained.