getting rid of the extra clanker docs

This commit is contained in:
peterino2 2026-01-24 18:00:34 -08:00
parent 4ffb701a36
commit 7c47116ff0
8 changed files with 0 additions and 2587 deletions

View File

@ -1,348 +0,0 @@
# API Reference
Complete reference for the SDL3 header parser command-line interface.
## Command Syntax
```bash
zig build run -- <header_file> [options]
```
## Arguments
### Required
**`<header_file>`** - Path to SDL C header file
Examples:
```bash
zig build run -- ../SDL/include/SDL3/SDL_gpu.h
zig build run -- /full/path/to/SDL_video.h
zig build run -- relative/path/to/header.h
```
### Optional
**`--output=<file>`** - Write output to file instead of stdout
Examples:
```bash
--output=gpu.zig
--output=bindings/video.zig
--output=/tmp/test.zig
```
**`--mocks=<file>`** - Generate C mock implementations
Examples:
```bash
--mocks=gpu_mock.c
--mocks=test/mocks.c
```
**`--generate-json=<file>`** - Generate JSON representation of parsed types
Examples:
```bash
--generate-json=gpu.json
--generate-json=api/types.json
```
## Output Formats
### Zig Bindings (Default)
Generated when `--output` is specified (or to stdout if not):
```zig
pub const c = @import("c.zig").c;
pub const GPUDevice = opaque {
pub inline fn createGPUDevice(debug_mode: bool) ?*GPUDevice {
return c.SDL_CreateGPUDevice(debug_mode);
}
};
```
**Features**:
- Type conversions (C → Zig)
- Method organization
- Dependency inclusion
- Doc comments preserved
### C Mocks (Optional)
Generated when `--mocks` is specified:
```c
// Auto-generated C mock implementations
#include <SDL3/SDL_gpu.h>
SDL_GPUDevice* SDL_CreateGPUDevice(bool debug_mode) {
return NULL; // Mock: always returns null
}
void SDL_DestroyGPUDevice(SDL_GPUDevice *device) {
// Mock: no-op
}
```
**Use Case**: Testing without real SDL implementation
### JSON Output (Optional)
Generated when `--generate-json` is specified:
```json
{
"header": "SDL_gpu.h",
"opaque_types": [
{"name": "SDL_GPUDevice"}
],
"typedefs": [
{"name": "SDL_PropertiesID", "underlying_type": "Uint32"}
],
"enums": [
{
"name": "SDL_GPUPrimitiveType",
"values": [
{"name": "SDL_GPU_PRIMITIVETYPE_TRIANGLELIST"},
{"name": "SDL_GPU_PRIMITIVETYPE_TRIANGLESTRIP"}
]
}
],
"structs": [
{
"name": "SDL_GPUViewport",
"fields": [
{"name": "x", "type": "float"},
{"name": "y", "type": "float"}
]
}
],
"functions": [
{
"name": "SDL_CreateGPUDevice",
"return_type": "SDL_GPUDevice*",
"parameters": [
{"name": "debug_mode", "type": "bool"}
]
}
]
}
```
**Use Cases**:
- API documentation generation
- Schema validation
- Cross-language binding generation
- Type introspection tools
## Build System Integration
### In build.zig
```zig
const parser_dep = b.dependency("sdl3_parser", .{
.target = target,
.optimize = optimize,
});
const parser_exe = parser_dep.artifact("sdl-parser");
const gen = b.addRunArtifact(parser_exe);
gen.addFileArg(b.path("SDL/include/SDL3/SDL_gpu.h"));
gen.addArg("--output=src/gpu.zig");
const gen_step = b.step("generate", "Generate SDL bindings");
gen_step.dependOn(&gen.step);
```
Then run:
```bash
zig build generate
```
## Parser Behavior
### Dependency Resolution
**Automatic** - No configuration needed
When the parser detects missing types, it:
1. Parses `#include` directives from the header
2. Searches each included header
3. Extracts matching type definitions
4. Includes them in the output
**Progress Reporting**:
```
Analyzing dependencies...
Found 5 missing types:
- SDL_Window
- SDL_Rect
...
Resolving dependencies...
✓ Found SDL_Window in SDL_video.h
✓ Found SDL_Rect in SDL_rect.h
```
### Type Filtering
Only SDL types are processed:
- Types starting with `SDL_`
- Known SDL types (Window, Rect, etc.)
Primitive types are ignored:
- `bool`, `int`, `float`, `void`, etc.
### Pattern Matching Order
Patterns are tried in this order:
1. Opaque types (`typedef struct X X;`)
2. Enums (`typedef enum {...} X;`)
3. Structs (`typedef struct {...} X;`)
4. Flags (`typedef Uint32 SDL_Flags;` + `#define` values)
5. Typedefs (`typedef Type SDL_Alias;`)
6. Functions (`extern SDL_DECLSPEC ...`)
**Note**: Order matters! Flags must be tried before simple typedefs.
### Naming Conventions
**Types**:
- `SDL_GPUDevice``GPUDevice` (strip `SDL_` prefix)
- `SDL_GPU_PRIMITIVE_TYPE``GPUPrimitiveType` (remove first underscore)
**Functions**:
- `SDL_CreateGPUDevice``createGPUDevice` (strip `SDL_`, camelCase)
**Enum Values**:
- `SDL_GPU_PRIMITIVETYPE_TRIANGLELIST``primitiveTypeTrianglelist`
**Parameters**:
- `SDL_GPUDevice *device``device: ?*GPUDevice`
## Exit Codes
- `0` - Success
- `1` - Error (file not found, out of memory, invalid arguments)
## Console Output
### Normal Operation
```
SDL3 Header Parser
==================
Parsing: header.h
Found N declarations
- Opaque types: X
- Typedefs: X
- Enums: X
- Structs: X
- Flags: X
- Functions: X
Analyzing dependencies...
[dependency information]
Generated: output.zig
```
File is still written, but may need manual fixes.
## Type Conversion Reference
### Integer Types
| C Type | Zig Type |
|--------|----------|
| `Uint8` | `u8` |
| `Uint16` | `u16` |
| `Uint32` | `u32` |
| `Uint64` | `u64` |
| `Sint8` | `i8` |
| `Sint16` | `i16` |
| `Sint32` | `i32` |
| `Sint64` | `i64` |
| `int` | `c_int` |
| `unsigned int` | `c_uint` |
| `size_t` | `usize` |
### Pointer Types
| C Type | Zig Type |
|--------|----------|
| `SDL_Type*` | `?*Type` (nullable) |
| `const SDL_Type*` | `*const Type` |
| `SDL_Type**` | `?*?*Type` |
| `void*` | `?*anyopaque` |
| `const void*` | `*const anyopaque` |
| `const char*` | `[*c]const u8` |
### Special Types
| C Type | Zig Type |
|--------|----------|
| `bool` | `bool` |
| `float` | `f32` |
| `double` | `f64` |
| `size_t` | `usize` |
## Examples
### Example
**Input** (depends.h):
```c
#include <SDL3/SDL_rect.h>
extern void SDL_UseRect(SDL_Rect *rect);
```
**Command**:
```bash
zig build run -- depends.h --output=depends.zig
```
**Output**:
```zig
pub const c = @import("c.zig").c;
// Dependency automatically included
pub const Rect = extern struct {
x: c_int,
y: c_int,
w: c_int,
h: c_int,
};
pub inline fn useRect(rect: *Rect) void {
return c.SDL_UseRect(rect);
}
```
### Mocks example
**Command**:
```bash
zig build run -- simple.h --output=thing.zig --mocks=thing_mock.c
```
**Output** (thing_mock.c):
```c
#include <SDL3/SDL.h>
SDL_ThingID SDL_CreateThing(void) {
return 0;
}
void SDL_DestroyThing(SDL_Thing *thing) {
// No-op
}
```

View File

@ -1,430 +0,0 @@
# ## Documentation
- **[README](../README.md)** - Project overview and quick start
- **[Getting Started](GETTING_STARTED.md)** - Installation and first steps
- **[Architecture](ARCHITECTURE.md)** - How the parser works
- **[Dependency Resolution](DEPENDENCY_RESOLUTION.md)** - Automatic type extraction
- **[API Reference](API_REFERENCE.md)** - Command-line options and features
- **[Known Issues](KNOWN_ISSUES.md)** - Limitations and workarounds
- **[Quickstart Guide](QUICKSTART.md)** - Quick reference
- **[Roadmap](ROADMAP.md)** - Future plans and priorities
## Technical Deep Dives
For implementation details and visual guides:
- **[Dependency Flow](DEPENDENCY_FLOW.md)** - Complete technical walkthrough
- **[Visual Flow Diagrams](VISUAL_FLOW.md)** - Quick reference diagrams
- **[Multi-Field Structs](MULTI_FIELD_IMPLEMENTATION.md)** - Struct parsing details
- **[Typedef Support](TYPEDEF_IMPLEMENTATION.md)** - Typedef implementation
- **[Multi-Header Testing](MULTI_HEADER_TEST_RESULTS.md)** - Test results
## Development
- **[Development Guide](DEVELOPMENT.md)** - Contributing and extending the parser
## Archive
Historical planning documents are in `archive/` for reference.
## High-Level Architecture
```
Input (C Header) → Scanner → Declarations → Dependency Resolver → CodeGen → Output (Zig)
```
## Core Components
### 1. Scanner (`src/patterns.zig`)
**Purpose**: Parse C header files into structured declarations
**Process**:
1. Reads header file line by line
2. Tries to match each line against known patterns
3. Extracts type information, comments, and structure
4. Returns array of `Declaration` structures
**Supported Patterns**:
- Opaque types: `typedef struct SDL_X SDL_X;`
- Typedefs: `typedef Uint32 SDL_PropertiesID;`
- Enums: `typedef enum { ... } SDL_Type;`
- Structs: `typedef struct { int x, y; } SDL_Rect;`
- Flags: `typedef Uint32 SDL_Flags;` + `#define` values
- Functions: `extern SDL_DECLSPEC void SDLCALL SDL_Func(...);`
### 2. Dependency Resolver (`src/dependency_resolver.zig`)
**Purpose**: Automatically find and extract missing type definitions
**Process**:
1. Scans all declarations to find referenced types
2. Compares referenced types against defined types
3. Identifies missing types
4. Parses `#include` directives from source
5. Searches included headers for missing types
6. Extracts and clones matching declarations
**Key Features**:
- Type string normalization (strips `*`, `const`, etc.)
- Deduplication using HashMaps
- Deep cloning for safe ownership
- Selective extraction (only types needed)
### 3. Code Generator (`src/codegen.zig`)
**Purpose**: Convert C declarations to idiomatic Zig code
**Process**:
1. Groups functions by first parameter type (method categorization)
2. Generates type declarations
3. Generates function wrappers
4. Applies naming conventions
5. Performs type conversion
**Features**:
- Method organization for opaque types
- Inline function wrappers
- Automatic type conversion
- Doc comment preservation
### 4. Type Converter (`src/types.zig`)
**Purpose**: Convert C types to Zig equivalents
**Conversions**:
```zig
"bool" → "bool"
"Uint32" → "u32"
"int" → "c_int"
"SDL_Type *" → "?*Type"
"const SDL_Type *" → "*const Type"
```
### 5. Naming Convention Handler (`src/naming.zig`)
**Purpose**: Convert C names to idiomatic Zig
**Rules**:
- Strip `SDL_` prefix: `SDL_GPUDevice``GPUDevice`
- Remove first underscore: `SDL_GPU_TYPE``GPUType`
- CamelCase functions: `SDL_CreateDevice``createDevice`
- Lowercase first letter for values
## Data Flow
### 1. Parsing Phase
```
C Header File
Scanner.scan()
[]Declaration {
.opaque_type,
.typedef_decl,
.enum_decl,
.struct_decl,
.flag_decl,
.function_decl,
}
```
### 2. Dependency Analysis Phase
```
[]Declaration
DependencyResolver.analyze()
├─ collectDefinedTypes() → defined_types HashMap
└─ collectReferencedTypes() → referenced_types HashMap
getMissingTypes()
missing_types = referenced - defined
```
### 3. Dependency Resolution Phase
```
For each missing_type:
Parse #include directives
For each included header:
Read header file
Scanner.scan()
Search for matching type
If found: cloneDeclaration()
```
### 4. Code Generation Phase
```
[]Declaration (primary + dependencies)
CodeGen.generate()
├─ categorizeDeclarations() (group methods)
├─ writeHeader()
└─ writeDeclarations()
├─ writeOpaqueWithMethods()
├─ writeTypedef()
├─ writeEnum()
├─ writeStruct()
├─ writeFlags()
└─ writeFunction()
Zig source code (string)
```
### 5. Validation Phase
```
Generated Zig code
std.zig.Ast.parse()
Check for syntax errors
ast.renderAlloc() (format)
Write to file or stdout
```
## Key Algorithms
### Type Extraction
**Purpose**: Strip pointer/const decorators to get base type
```zig
"SDL_Window *" → "SDL_Window"
"?*const SDL_Rect" → "SDL_Rect"
"SDL_Buffer *const *" → "SDL_Buffer"
```
**Algorithm**:
1. Trim whitespace
2. Remove leading qualifiers (`const`, `*`, `?`)
3. Remove trailing qualifiers (`*`, `*const`, ` const`)
4. Handle special patterns (`[*c]`)
5. Return base type string
### Multi-Field Parsing
**Purpose**: Handle C compact syntax like `int x, y;`
**Algorithm**:
1. Detect comma in field declaration
2. Extract common type (before first field name)
3. Split remaining part on commas
4. Create separate `FieldDecl` for each name
5. Return array of fields
**Example**:
```c
int x, y; → [FieldDecl{.name="x", .type="int"},
FieldDecl{.name="y", .type="int"}]
```
### Method Categorization
**Purpose**: Determine if function should be a method
**Algorithm**:
1. Check if function has parameters
2. Get type of first parameter
3. Check if type is an opaque type pointer
4. If yes, add to opaque type's methods
5. If no, write as standalone function
**Example**:
```c
void SDL_Destroy(SDL_Device *d) → Method of GPUDevice
void SDL_Init(void) → Standalone function
```
## Memory Management
### Ownership Rules
1. **Scanner owns strings** during parsing (allocated from its allocator)
2. **Parser owns declarations** after scanning (freed at end of main)
3. **Resolver owns HashMap keys** (duped when inserted, freed in deinit)
4. **Cloned declarations own strings** (allocated explicitly, freed by caller)
### Allocation Strategy
```
GPA (General Purpose Allocator)
├─ Primary header source (freed at end)
├─ Primary declarations (freed with deep free)
├─ DependencyResolver
│ ├─ referenced_types HashMap (keys owned)
│ └─ defined_types HashMap (keys borrowed)
├─ Missing types array (freed explicitly)
├─ Includes array (freed explicitly)
├─ Dependency declarations (freed with deep free)
└─ Generated output (freed after writing)
```
### Cleanup Pattern
```zig
defer {
for (decls) |decl| {
freeDeclDeep(allocator, decl);
}
allocator.free(decls);
}
```
## Error Handling
### Fatal Errors (Exit Immediately)
- File not found (primary header)
- Out of memory
- Cannot write output file
### Non-Fatal Errors (Continue with Warnings)
- Dependency header not readable → Skip, try next
- Type not found in any header → Print warning, continue
- Struct parsing error → Generate partial, continue
- Syntax errors in output → Print errors, write anyway
### Error Recovery
The parser uses graceful degradation:
1. Try to extract as much as possible
2. Warn about issues
3. Continue processing
4. Generate best-effort output
This allows partial success even with problematic headers.
## Extension Points
### Adding New Pattern Support
1. Add new variant to `Declaration` union in `patterns.zig`
2. Implement `scan*()` function to match pattern
3. Add to pattern matching chain in `Scanner.scan()`
4. Update all switch statements:
- Cleanup code in `parser.zig`
- `cloneDeclaration()` in `dependency_resolver.zig`
- `freeDeclaration()` in `dependency_resolver.zig`
5. Implement `write*()` in `codegen.zig`
### Adding Type Conversions
Edit `src/types.zig`:
```zig
pub fn convertType(c_type: []const u8, allocator: Allocator) ![]const u8 {
// Add new conversion here
if (std.mem.eql(u8, c_type, "MyType")) {
return try allocator.dupe(u8, "MyZigType");
}
// ...
}
```
### Adding Naming Rules
Edit `src/naming.zig`:
```zig
pub fn typeNameToZig(c_name: []const u8) []const u8 {
// Add custom naming logic
}
```
## Performance Characteristics
### Time Complexity
- **Primary parsing**: O(n) where n = source lines
- **Dependency analysis**: O(d) where d = declarations
- **Type extraction**: O(h × d) where h = headers, d = declarations per header
- **Code generation**: O(d) where d = total declarations
**Overall**: O(n + h×d) - Linear for typical use
### Space Complexity
- **Declarations**: O(d) where d = declaration count
- **HashMaps**: O(t) where t = unique type names
- **Output**: O(d) where d = declaration count
**Peak memory**: ~2-5MB for SDL_gpu.h (169 declarations)
### Optimization Points
Current optimizations:
- HashMap-based deduplication
- Early exit when type found
- Selective parsing (only missing types)
- String interning for type names
Potential improvements:
- Cache parsed headers (avoid re-parsing)
- Parallel header processing
- Lazy header loading
## Testing Strategy
### Unit Tests (`test/`)
- Pattern matching tests (each C pattern)
- Type conversion tests
- Naming convention tests
- Dependency resolution tests
- Multi-field parsing tests
### Integration Tests
- Real SDL headers (SDL_gpu.h)
- Dependency chain resolution
- End-to-end parsing and generation
### Validation
- AST parsing of generated code
- Memory leak detection (GPA)
- No regressions (all tests must pass)
## Code Organization
```
src/
├── parser.zig # Main entry point, CLI handling
├── patterns.zig # Pattern matching and scanning
├── types.zig # C to Zig type conversion
├── naming.zig # Naming convention handling
├── codegen.zig # Zig code generation
├── mock_codegen.zig # C mock generation
└── dependency_resolver.zig # Dependency analysis and extraction
test/
└── (various test files)
docs/
├── GETTING_STARTED.md # This file
├── ARCHITECTURE.md # Architecture overview
├── DEPENDENCY_RESOLUTION.md # Dependency system details
└── ...
```
## Next Steps
- Read [Dependency Resolution](DEPENDENCY_RESOLUTION.md) for details on automatic type extraction
- See [API Reference](API_REFERENCE.md) for all command-line options
- Check [Known Issues](KNOWN_ISSUES.md) for current limitations
- Review [Development](DEVELOPMENT.md) to contribute
---
**Related Documents**:
- Technical deep dive: [docs/DEPENDENCY_FLOW.md](DEPENDENCY_FLOW.md)
- Visual diagrams: [docs/VISUAL_FLOW.md](VISUAL_FLOW.md)

View File

@ -1,283 +0,0 @@
# Dependency Resolution System
The parser automatically detects and resolves type dependencies from SDL headers.
## Overview
When parsing a header like SDL_gpu.h, functions often reference types defined in other headers (SDL_Window, SDL_Rect, etc.). The dependency resolver automatically finds and includes these types.
## How It Works
### Step 1: Detect Missing Types
After parsing the primary header, the system:
1. Scans all function signatures and struct fields
2. Extracts all referenced type names
3. Compares against types defined in the header
4. Identifies missing types
**Example**:
```c
// SDL_gpu.h
extern void SDL_ClaimWindow(SDL_GPUDevice *device, SDL_Window *window);
```
- `SDL_GPUDevice` is defined in SDL_gpu.h ✓
- `SDL_Window` is NOT defined in SDL_gpu.h ✗
**Result**: SDL_Window added to missing types list
### Step 2: Parse Include Directives
Extracts `#include` directives from the header:
```c
#include <SDL3/SDL_stdinc.h>
#include <SDL3/SDL_video.h>
#include <SDL3/SDL_rect.h>
```
**Result**: List of headers to search: [`SDL_stdinc.h`, `SDL_video.h`, `SDL_rect.h`]
### Step 3: Search for Missing Types
For each missing type:
1. Try each included header in order
2. Parse the header completely
3. Search for matching type definition
4. If found, clone the declaration and stop searching
5. If not found, continue to next header
**Example Search for SDL_Window**:
```
Try SDL_stdinc.h → Not found
Try SDL_video.h → Found! ✓
└─ Extract SDL_Window definition
└─ Stop searching
```
### Step 4: Combine Declarations
```zig
final_declarations = [
// Dependencies FIRST (so types are defined before use)
SDL_Window,
SDL_Rect,
SDL_FColor,
// Primary declarations
SDL_GPUDevice,
SDL_GPUTexture,
...
]
```
### Step 5: Generate Unified Output
```zig
pub const c = @import("c.zig").c;
// Dependencies (automatically included)
pub const Window = opaque {};
pub const Rect = extern struct { x: c_int, y: c_int, w: c_int, h: c_int };
// Primary declarations
pub const GPUDevice = opaque {
pub fn claimWindow(device: *GPUDevice, window: ?*Window) bool {
return c.SDL_ClaimWindowForGPUDevice(device, window);
}
};
```
## Type Extraction Details
### Type String Normalization
C type strings often have pointer and const decorators that need to be stripped:
```
"SDL_Window *" → "SDL_Window"
"?*SDL_GPUDevice" → "SDL_GPUDevice"
"*const SDL_Rect" → "SDL_Rect"
"SDL_Buffer *const *" → "SDL_Buffer"
"[*c]const u8" → "u8"
```
**Algorithm**:
1. Remove leading: `const`, `struct`, `?`, `*`
2. Handle C arrays: `[*c]T``T`
3. Remove trailing: `*`, `*const`, ` const`
4. Repeat until no changes
### SDL Type Detection
A type is considered "SDL" if:
- Name starts with `SDL_` prefix, OR
- Name is in known SDL types list (Window, Rect, etc.)
Non-SDL types (primitives) are ignored:
- `bool`, `int`, `float`, `void`, etc.
### Declaration Cloning
When extracting types from dependency headers, we must clone them because:
1. The temporary scanner will be freed
2. Original strings will be deallocated
3. We need owned copies with stable lifetime
**Cloning Process**:
```zig
fn cloneDeclaration(allocator: Allocator, decl: Declaration) !Declaration {
return switch (decl) {
.struct_decl => |s| .{
.struct_decl = .{
.name = try allocator.dupe(u8, s.name),
.fields = try cloneFields(allocator, s.fields),
.doc_comment = if (s.doc_comment) |doc|
try allocator.dupe(u8, doc) else null,
},
},
// ... similar for other types
};
}
```
All strings are duplicated so the cloned declaration owns them.
## Success Metrics
### SDL_gpu.h Results
**Missing Types Detected**: 5
1. SDL_FColor
2. SDL_PropertiesID
3. SDL_Rect
4. SDL_Window
5. SDL_FlipMode
**Resolution Results**: 5/5 (100%) ✅
**Where Found**:
- SDL_FColor → SDL_pixels.h (struct)
- SDL_PropertiesID → SDL_properties.h (typedef)
- SDL_Rect → SDL_rect.h (struct)
- SDL_Window → SDL_video.h (opaque)
- SDL_FlipMode → SDL_surface.h (enum)
## Configuration
### Behavior
The dependency resolver is **always enabled** - no configuration needed.
When missing types are detected, it automatically:
- ✅ Searches included headers
- ✅ Extracts matching types
- ✅ Combines into output
- ✅ Reports progress
### Error Handling
**Warnings** (non-fatal):
- Type not found in any header
- Dependency header not readable
- Parsing errors in dependency
**Result**: Partial output with warnings
## Performance
### Timing Breakdown (SDL_gpu.h)
| Phase | Time | Notes |
|-------|------|-------|
| Primary parsing | 50ms | Parse SDL_gpu.h |
| Dependency analysis | 10ms | Build HashMaps |
| Include parsing | 1ms | Extract #includes |
| Type extraction | 300ms | Parse 5 dependency headers |
| Code generation | 150ms | Generate + validate |
| **Total** | **~520ms** | Acceptable |
### Optimization
**Current**:
- Selective parsing (only types needed)
- Early exit (stop when found)
- HashMap deduplication
**Future**:
- Cache parsed headers
- Parallel header parsing
- Header dependency graph
## Limitations
### Not Resolved
1. **Function pointer typedefs** - Not yet supported
```c
typedef void (*SDL_Callback)(void *userdata);
```
2. **#define-based types** - Requires preprocessor
```c
#define SDL_VALUE (1u << 0)
typedef Uint32 SDL_Type; // Not found by scanner
```
3. **External library types** - Expected
```c
SDL_EGLConfig // From EGL, not SDL
```
### Workarounds
**Manual Definitions**: Add missing types to a separate file
```zig
// manual_types.zig
pub const Callback = *const fn(?*anyopaque) void;
```
**Preprocessor**: Use clang to preprocess before parsing
```bash
clang -E -I/path/to/SDL3 header.h | zig build run --
```
## Debugging
### Enable Verbose Output
The parser already prints detailed progress:
```
Analyzing dependencies...
Found 5 missing types:
- SDL_FColor
- SDL_Rect
...
Resolving dependencies from included headers...
✓ Found SDL_FColor in SDL_pixels.h
✓ Found SDL_Rect in SDL_rect.h
⚠ Warning: Could not find definition for type: SDL_Unknown
```
### Common Issues
**"Could not find definition for type"**
- Type might be typedef (check if recently added)
- Type might be in different include
- Type might be external (EGL, GL, etc.)
**"Syntax errors in generated code"**
- Check generated file line numbers
- Usually struct/enum parsing issues
- See [Known Issues](KNOWN_ISSUES.md)
## Technical Details
For implementation details, see:
- [Technical Flow](DEPENDENCY_FLOW.md) - Step-by-step walkthrough
- [Visual Guide](VISUAL_FLOW.md) - Diagrams and quick reference
---
**Next**: See [API Reference](API_REFERENCE.md) for command-line options.

View File

@ -1,634 +0,0 @@
# Development Guide
Guide for contributing to and extending the SDL3 header parser.
## Quick Start for Developers
```bash
# Clone and build
cd lib/sdl3/parser
zig build
# Run tests
zig build test
# Make changes
# ... edit src/*.zig ...
# Test your changes
zig build test
zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=test.zig
```
## Project Structure
```
parser/
├── src/
│ ├── parser.zig # Main entry point, CLI
│ ├── patterns.zig # Pattern matching & scanning
│ ├── types.zig # C to Zig type conversion
│ ├── naming.zig # Naming conventions
│ ├── codegen.zig # Zig code generation
│ ├── mock_codegen.zig # C mock generation
│ └── dependency_resolver.zig # Dependency analysis
├── test/
│ └── (test files)
├── docs/
│ └── (documentation)
└── build.zig
```
## Zig 0.15 API Changes - CRITICAL
**This project uses Zig 0.15**. Key API changes from 0.14:
### ArrayList Changes
**Old (0.14)**:
```zig
var list = std.ArrayList(T).init(allocator);
defer list.deinit();
try list.append(item);
```
**New (0.15)** - REQUIRED:
```zig
var list = std.ArrayList(T){};
defer list.deinit(allocator);
try list.append(allocator, item);
```
**Key Points**:
- Initialize with `{}` or `initCapacity()`
- All methods take allocator: `append(allocator, item)`
- Deinit takes allocator: `deinit(allocator)`
### AST Rendering
**Old**: `ast.render(allocator)`
**New**: `ast.renderAlloc(allocator)`
## Adding New Pattern Support
### Example: Adding Union Support
1. **Add to Declaration union** (patterns.zig):
```zig
pub const Declaration = union(enum) {
// ... existing variants
union_decl: UnionDecl, // NEW
};
pub const UnionDecl = struct {
name: []const u8,
fields: []FieldDecl,
doc_comment: ?[]const u8,
};
```
2. **Add scanner function** (patterns.zig):
```zig
fn scanUnion(self: *Scanner) !?UnionDecl {
// Pattern matching logic
// Return UnionDecl or null
}
```
3. **Add to scan chain** (patterns.zig):
```zig
if (try self.scanOpaque()) |opaque_decl| {
// ...
} else if (try self.scanUnion()) |union_decl| {
try decls.append(self.allocator, .{ .union_decl = union_decl });
} else if (try self.scanEnum()) |enum_decl| {
// ...
}
```
4. **Update cleanup code** (parser.zig):
```zig
defer {
for (decls) |decl| {
switch (decl) {
// ... existing cases
.union_decl => |u| {
allocator.free(u.name);
if (u.doc_comment) |doc| allocator.free(doc);
for (u.fields) |field| {
allocator.free(field.name);
allocator.free(field.type_name);
if (field.comment) |c| allocator.free(c);
}
allocator.free(u.fields);
},
}
}
}
```
5. **Update dependency resolver** (dependency_resolver.zig):
```zig
// In collectDefinedTypes:
.union_decl => |u| u.name,
// In cloneDeclaration:
.union_decl => |u| .{
.union_decl = .{
.name = try allocator.dupe(u8, u.name),
.fields = try cloneFields(allocator, u.fields),
.doc_comment = if (u.doc_comment) |doc|
try allocator.dupe(u8, doc) else null,
},
},
// In freeDeclaration:
.union_decl => |u| {
allocator.free(u.name);
if (u.doc_comment) |doc| allocator.free(doc);
for (u.fields) |field| {
allocator.free(field.name);
allocator.free(field.type_name);
if (field.comment) |c| allocator.free(c);
}
allocator.free(u.fields);
},
```
6. **Add code generator** (codegen.zig):
```zig
fn writeUnion(self: *CodeGen, union_decl: patterns.UnionDecl) !void {
const zig_name = naming.typeNameToZig(union_decl.name);
if (union_decl.doc_comment) |doc| {
try self.writeDocComment(doc);
}
try self.output.writer(self.allocator).print(
"pub const {s} = extern union {{\n",
.{zig_name}
);
for (union_decl.fields) |field| {
const zig_type = try types.convertType(field.type_name, self.allocator);
defer self.allocator.free(zig_type);
try self.output.writer(self.allocator).print(
" {s}: {s},\n",
.{field.name, zig_type}
);
}
try self.output.appendSlice(self.allocator, "};\n\n");
}
```
7. **Update writeDeclarations** (codegen.zig):
```zig
switch (decl) {
// ... existing cases
.union_decl => |union_decl| try self.writeUnion(union_decl),
}
```
8. **Add tests**:
```zig
test "parse union" {
const source =
\\typedef union SDL_Color {
\\ Uint32 rgba;
\\ struct { Uint8 r, g, b, a; };
\\} SDL_Color;
;
var scanner = patterns.Scanner.init(allocator, source);
const decls = try scanner.scan();
// ... test expectations
}
```
## Testing Guidelines
### Unit Tests
Place tests in `test/` or at bottom of source files:
```zig
test "descriptive test name" {
const allocator = std.testing.allocator;
// Setup
const source = "...";
var scanner = patterns.Scanner.init(allocator, source);
// Execute
const result = try scanner.scan();
defer allocator.free(result);
// Assert
try std.testing.expectEqual(expected, actual);
}
```
### Integration Tests
Test with real SDL headers:
```bash
zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=test.zig
zig ast-check test.zig
```
### Memory Testing
Always run tests with GPA to detect leaks:
```zig
test "my test" {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Test code using allocator
}
```
## Code Style
### Naming
- **Functions**: camelCase (`parseStructField`)
- **Types**: PascalCase (`FieldDecl`)
- **Constants**: PascalCase (`Declaration`)
- **Variables**: camelCase (`decl_name`)
### Comments
Only comment code that needs clarification:
```zig
// Good: Explains WHY
// Must check flags before typedefs - pattern order matters
if (try self.scanFlagTypedef()) |flag_decl| { ... }
// Bad: Explains WHAT (obvious from code)
// Append to list
try list.append(allocator, item);
```
### Error Handling
Use graceful degradation:
```zig
// Good: Continue on error
const decl = extractType(source, name) catch |err| {
std.debug.print("Warning: {}\n", .{err});
continue;
};
// Bad: Fail immediately (unless truly fatal)
const decl = try extractType(source, name);
```
## Memory Management Rules
### Ownership
1. **Scanner owns strings** during parsing
2. **Caller owns result** of scan()
3. **HashMap owns keys** when they're duped
4. **Cloned declarations own strings** after cloning
### Cleanup Pattern
Always use defer for cleanup:
```zig
const decls = try scanner.scan();
defer {
for (decls) |decl| {
freeDeclDeep(allocator, decl);
}
allocator.free(decls);
}
```
### HashMap Keys
Must be owned (not slices into temporary data):
```zig
// Wrong:
try map.put(type_str, {}); // type_str might be freed!
// Right:
if (!map.contains(type_str)) {
const owned = try allocator.dupe(u8, type_str);
try map.put(owned, {});
}
```
## Common Patterns
### Pattern Matching
```zig
fn scanSomething(self: *Scanner) !?SomeDecl {
const start = self.pos;
const line = try self.readLine();
defer self.allocator.free(line);
// Check pattern
if (!std.mem.startsWith(u8, line, "expected_start")) {
self.pos = start; // Reset position
return null;
}
// Parse and return
return SomeDecl{ ... };
}
```
### String Building
```zig
var buf = std.ArrayList(u8){};
defer buf.deinit(allocator);
try buf.appendSlice(allocator, "pub const ");
try buf.appendSlice(allocator, name);
try buf.appendSlice(allocator, " = ");
return try buf.toOwnedSlice(allocator);
```
### HashMap Usage
```zig
var map = std.StringHashMap(void).init(allocator);
defer {
var it = map.keyIterator();
while (it.next()) |key| {
allocator.free(key.*); // Free owned keys
}
map.deinit();
}
// Add items
const owned_key = try allocator.dupe(u8, key);
try map.put(owned_key, {});
```
## Debugging Tips
### Print Debugging
```zig
std.debug.print("Debug: value = {s}\n", .{value});
std.debug.print("Type: {}\n", .{@TypeOf(variable)});
```
### Memory Leak Detection
Run with GPA and check output:
```bash
zig build run -- header.h 2>&1 | grep "memory address"
```
### AST Debugging
Check what Zig thinks is wrong:
```bash
zig ast-check generated.zig
```
## Performance Optimization
### Guidelines
1. **Avoid allocations in hot paths** - Use stack when possible
2. **Reuse buffers** - Clear and reuse instead of allocating new
3. **Early exit** - Return as soon as answer is known
4. **HashMap for lookups** - O(1) instead of O(n) searches
### Profiling
```bash
# Build with profiling
zig build -Drelease-safe
# Run with timing
time zig build run -- large_header.h --output=out.zig
```
## Contributing Workflow
1. **Create branch** from `dev/sdl3-parser`
2. **Make changes** in focused commits
3. **Run tests** - All must pass
4. **Update docs** if behavior changes
5. **Commit** with descriptive message
6. **Push** and create PR
### Commit Message Format
```
feat: Add union type support
Implements parsing and code generation for C union types.
- Added UnionDecl to Declaration union
- Implemented scanUnion() pattern matcher
- Added writeUnion() code generator
- Created comprehensive test suite (5 tests)
Results:
- Successfully parses SDL union types
- Generates proper extern unions
- All tests passing
Closes: #123
```
## Test-Driven Development
Recommended workflow:
1. **Write test first**:
```zig
test "parse union type" {
const source = "typedef union { int x; float y; } SDL_Union;";
var scanner = patterns.Scanner.init(allocator, source);
const decls = try scanner.scan();
try testing.expectEqual(@as(usize, 1), decls.len);
try testing.expect(decls[0] == .union_decl);
}
```
2. **Run test** (it will fail)
3. **Implement feature** until test passes
4. **Add more tests** for edge cases
5. **Refactor** if needed
## Architecture Decisions
### Why Single-File Output?
**Alternative**: Generate separate file per type
**Decision**: Single file with dependencies first
**Reasons**:
- Simpler for users (one import)
- Zig's structural typing handles it
- Type ordering guaranteed
- Less build system complexity
### Why On-Demand Resolution?
**Alternative**: Always parse all includes
**Decision**: Only parse when missing types detected
**Reasons**:
- Better performance
- Minimal overhead for self-contained headers
- Users see only relevant dependencies
### Why Conservative Error Handling?
**Alternative**: Fail on any error
**Decision**: Warn and continue
**Reasons**:
- Partial success is better than no success
- Users can manually fix issues
- Allows incremental improvement
## Extending the Parser
### Adding Type Conversions
Edit `src/types.zig`:
```zig
pub fn convertType(c_type: []const u8, allocator: Allocator) ![]const u8 {
// Check for your pattern first
if (std.mem.eql(u8, c_type, "MyCustomType")) {
return try allocator.dupe(u8, "MyZigType");
}
// Fall through to existing logic
// ...
}
```
### Adding Naming Rules
Edit `src/naming.zig`:
```zig
pub fn typeNameToZig(c_name: []const u8) []const u8 {
// Handle special cases
if (std.mem.eql(u8, c_name, "SDL_bool")) {
return "Bool"; // Custom mapping
}
// Default logic
return stripSDLPrefix(c_name);
}
```
### Adding Pattern Matchers
1. Implement `scan*()` function in `patterns.zig`
2. Add to scan chain with proper ordering
3. Update all switch statements
4. Add code generator
5. Write tests
See "Adding New Pattern Support" section above for full example.
## Common Issues When Developing
### Issue: ArrayList API Changed
**Error**: `error: no field named 'init' in struct 'ArrayList'`
**Solution**: Use Zig 0.15 API (see above)
### Issue: HashMap Key Lifetime
**Error**: Memory corruption or use-after-free
**Solution**: Always dupe keys before inserting:
```zig
const owned = try allocator.dupe(u8, key);
try map.put(owned, {});
```
### Issue: Pattern Matching Order
**Error**: Wrong scanner function matches
**Solution**: Order matters! More specific patterns first:
```zig
// Correct order:
if (try self.scanFlagTypedef()) { ... } // Specific
else if (try self.scanTypedef()) { ... } // General
// Wrong order:
if (try self.scanTypedef()) { ... } // Too general - catches flags!
else if (try self.scanFlagTypedef()) { ... } // Never reached
```
## Performance Considerations
### Current Performance
- Small headers: ~100ms
- Large headers (SDL_gpu.h): ~520ms
- Memory: ~2-5MB peak
### Bottlenecks
1. **Dependency extraction**: 300ms (58% of time)
- Parsing multiple headers
- Could cache parsed headers
2. **String allocations**: Many small allocations
- Could use arena allocator
- String interning would help
### Optimization Ideas
```zig
// Cache parsed headers
var header_cache = std.StringHashMap([]Declaration).init(allocator);
// Use arena for temporary allocations
var arena = std.heap.ArenaAllocator.init(allocator);
defer arena.deinit();
const temp_alloc = arena.allocator();
```
## Resources
### Zig Documentation
- [Zig Language Reference](https://ziglang.org/documentation/master/)
- [Zig Standard Library](https://ziglang.org/documentation/master/std/)
### SDL Documentation
- [SDL3 API](https://wiki.libsdl.org/SDL3/)
- [SDL3 Headers](https://github.com/libsdl-org/SDL)
### Project Documentation
- [Architecture](ARCHITECTURE.md) - How the parser works
- [Dependency Flow](DEPENDENCY_FLOW.md) - Detailed flow
- [Visual Flow](VISUAL_FLOW.md) - Diagrams
## Getting Help
- Check existing tests for examples
- Read [Architecture](ARCHITECTURE.md) for design
- See [Dependency Flow](DEPENDENCY_FLOW.md) for details
- Review git history for patterns
---
**Ready to contribute?** Start with the tests, understand the existing patterns, then extend!

View File

@ -1,278 +0,0 @@
# Getting Started with SDL3 Parser
This guide will help you get up and running with the SDL3 header parser.
## Prerequisites
- Zig 0.15 or later
- SDL3 headers (included in `../SDL/include/SDL3/`)
## Installation
1. Navigate to the parser directory:
```bash
cd lib/sdl3/parser
```
2. Build the parser:
```bash
zig build
```
3. Run tests to verify installation:
```bash
zig build test
```
You should see: `All tests passed.`
## Your First Parse
### Step 1: Parse SDL_gpu.h
```bash
zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=my_gpu.zig
```
You'll see output like:
```
SDL3 Header Parser
==================
Parsing: ../SDL/include/SDL3/SDL_gpu.h
Found 169 declarations
- Opaque types: 13
- Typedefs: 6
- Enums: 24
- Structs: 35
- Flags: 3
- Functions: 94
Analyzing dependencies...
Found 5 missing types:
- SDL_FColor
- SDL_PropertiesID
- SDL_Rect
- SDL_Window
- SDL_FlipMode
Resolving dependencies from included headers...
✓ Found SDL_FColor in SDL_pixels.h
✓ Found SDL_PropertiesID in SDL_properties.h
✓ Found SDL_Rect in SDL_rect.h
✓ Found SDL_Window in SDL_video.h
✓ Found SDL_FlipMode in SDL_surface.h
Combining 5 dependency declarations with primary declarations...
Generated: my_gpu.zig
```
### Step 2: Examine the Output
```bash
head -50 my_gpu.zig
```
You'll see clean Zig bindings:
```zig
pub const c = @import("c.zig").c;
// Dependencies (automatically included)
pub const FColor = extern struct {
r: f32,
g: f32,
b: f32,
a: f32,
};
pub const PropertiesID = u32;
pub const Rect = extern struct {
x: c_int,
y: c_int,
w: c_int,
h: c_int,
};
pub const Window = opaque {};
// Primary declarations
pub const GPUDevice = opaque {
pub inline fn destroyGPUDevice(gpudevice: *GPUDevice) void {
return c.SDL_DestroyGPUDevice(gpudevice);
}
// ... 93 more methods
};
```
### Step 3: Create c.zig Wrapper
Create a file `c.zig` that imports SDL:
```zig
pub const c = @cImport({
@cInclude("SDL3/SDL.h");
});
```
### Step 4: Use in Your Project
```zig
const std = @import("std");
const gpu = @import("my_gpu.zig");
pub fn main() !void {
const device = gpu.createGPUDevice(true);
if (device) |d| {
defer d.destroyGPUDevice();
const driver = d.getGPUDeviceDriver();
std.debug.print("GPU Driver: {s}\n", .{driver});
}
}
```
## Command-Line Options
### Basic Options
```bash
# Output to file
zig build run -- header.h --output=output.zig
# Output to stdout
zig build run -- header.h
```
### Mock Generation
```bash
# Generate C mocks for testing
zig build run -- header.h --output=bindings.zig --mocks=mocks.c
```
The mock file contains stub implementations that return zero/null:
```c
void SDL_DestroyGPUDevice(SDL_GPUDevice *device) {
// Mock implementation
}
```
## Understanding the Output
### Type Name Conversion
The parser follows consistent naming rules:
| C Name | Zig Name | Rule |
|--------|----------|------|
| `SDL_GPUDevice` | `GPUDevice` | Strip `SDL_` prefix |
| `SDL_GPU_PRIMITIVE_TYPE_TRIANGLELIST` | `primitiveTypeTrianglelist` | Strip prefix, camelCase |
| `SDL_CreateGPUDevice` | `createGPUDevice` | Strip `SDL_`, camelCase |
### Method Grouping
Functions are organized as methods when possible:
**C API**:
```c
void SDL_DestroyGPUDevice(SDL_GPUDevice *device);
const char* SDL_GetGPUDeviceDriver(SDL_GPUDevice *device);
```
**Generated Zig**:
```zig
pub const GPUDevice = opaque {
pub inline fn destroyGPUDevice(self: *GPUDevice) void { ... }
pub inline fn getGPUDeviceDriver(self: *GPUDevice) [*c]const u8 { ... }
};
```
Usage becomes:
```zig
device.destroyGPUDevice(); // Instead of SDL_DestroyGPUDevice(device)
```
### Dependency Inclusion
Dependencies are automatically detected and included at the top of the file:
```zig
// Dependencies from included headers
pub const FColor = extern struct { ... };
pub const Rect = extern struct { ... };
pub const Window = opaque {};
// Primary declarations from SDL_gpu.h
pub const GPUDevice = opaque { ... };
```
## Common Workflows
### Generate Bindings for a Module
```bash
# From lib/sdl3 directory
zig build regenerate-zig
```
This generates bindings for configured headers in `v2/` directory.
### Test Your Changes
After modifying the parser:
```bash
# Run unit tests
zig build test
# Test with a real header
zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=test.zig
# Verify output compiles
zig ast-check test.zig
```
### Debug Issues
If you encounter errors:
1. Check the console output for warnings about missing types
2. Look at the generated file for syntax errors
3. See [Known Issues](docs/KNOWN_ISSUES.md) for common problems
## Next Steps
- Read [Architecture](docs/ARCHITECTURE.md) to understand how it works
- See [Dependency Resolution](docs/DEPENDENCY_RESOLUTION.md) for details on automatic type extraction
- Check [Known Issues](docs/KNOWN_ISSUES.md) for current limitations
- Review [Development](docs/DEVELOPMENT.md) to contribute
## Quick Reference
```bash
# Build
zig build
# Test
zig build test
# Generate bindings
zig build run -- <header> --output=<output>
# Generate with mocks
zig build run -- <header> --output=<output> --mocks=<mocks>
# Generate all configured headers
cd .. && zig build regenerate-zig
```
## Getting Help
- **Documentation**: See `docs/` directory
- **Examples**: Check `test/` directory for usage examples
- **Issues**: See `docs/KNOWN_ISSUES.md`
---
**Next**: Read [Architecture](docs/ARCHITECTURE.md) to understand the parser internals.

View File

@ -1,112 +0,0 @@
# SDL3 Parser Documentation
Complete documentation for the SDL3 C header to Zig bindings generator.
## Quick Links
- **[README](../README.md)** - Start here for project overview
- **[Getting Started](GETTING_STARTED.md)** - Installation and first use
- **[API Reference](API_REFERENCE.md)** - Command-line options
## User Guides
### Essential
1. **[Getting Started](GETTING_STARTED.md)** - Installation, first parse, basic usage
2. **[Quickstart Guide](QUICKSTART.md)** - Quick reference for common tasks
3. **[API Reference](API_REFERENCE.md)** - Complete command-line reference
### Features
4. **[Dependency Resolution](DEPENDENCY_RESOLUTION.md)** - How automatic type extraction works
5. **[Known Issues](KNOWN_ISSUES.md)** - Current limitations and workarounds
## Technical Documentation
### Architecture
6. **[Architecture Overview](ARCHITECTURE.md)** - System design and components
7. **[Dependency Flow](DEPENDENCY_FLOW.md)** - Complete technical walkthrough (845 lines)
8. **[Visual Flow Diagrams](VISUAL_FLOW.md)** - Quick reference diagrams
### Implementation Details
9. **[Multi-Field Structs](MULTI_FIELD_IMPLEMENTATION.md)** - How `int x, y;` parsing works
10. **[Typedef Support](TYPEDEF_IMPLEMENTATION.md)** - Simple typedef implementation
11. **[Multi-Header Testing](MULTI_HEADER_TEST_RESULTS.md)** - Test results across SDL headers
## Development
12. **[Development Guide](DEVELOPMENT.md)** - Contributing, extending, Zig 0.15 guidelines
13. **[Roadmap](ROADMAP.md)** - Future plans and priorities
## Quick Start
```bash
# Install
cd parser/
zig build
zig build test
# Generate bindings
zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=gpu.zig
# Use in code
const gpu = @import("gpu.zig");
```
## Documentation by Use Case
### "I want to generate Zig bindings"
→ Start with [Getting Started](GETTING_STARTED.md)
### "I want to understand how it works"
→ Read [Architecture](ARCHITECTURE.md)
### "I'm hitting an error"
→ Check [Known Issues](KNOWN_ISSUES.md)
### "I want to extend the parser"
→ See [Development Guide](DEVELOPMENT.md)
### "I need technical details"
→ Deep dive: [Dependency Flow](DEPENDENCY_FLOW.md)
## Project Status
**Version**: 2.1
**Status**: Production ready for SDL_gpu.h
**Last Updated**: 2026-01-22
### Supported Headers
| Header | Status | Notes |
|--------|--------|-------|
| SDL_gpu.h | ✅ Complete | 100% dependency resolution |
| SDL_keyboard.h | ⚠️ Partial | Large enum issues |
| SDL_video.h | ⚠️ Partial | Some types not found |
| SDL_events.h | ⚠️ Partial | Parse errors |
See [Known Issues](KNOWN_ISSUES.md) for details.
## Key Features
✅ Automatic dependency resolution (100% for SDL_gpu.h)
✅ Multi-field struct parsing (`int x, y;`)
✅ Typedef support (`typedef Uint32 SDL_Type;`)
✅ Method organization (functions → methods)
✅ Mock generation for testing
✅ Comprehensive error reporting
## Statistics
- **Code**: ~900 lines (production)
- **Tests**: 26+ unit tests (100% passing)
- **Documentation**: 5,500+ lines
- **Success Rate**: 100% for SDL_gpu.h
---
## Archive
Historical planning and session documents are in `archive/` for reference.

View File

@ -1,299 +0,0 @@
# Known Issues and Limitations
This document lists current limitations and remaining issues in the SDL3 header parser.
## Current Status
**45+ SDL3 headers** successfully generated with automatic dependency resolution and JSON export.
### Successfully Generated APIs
All major SDL3 APIs parse and generate correctly, including:
- Core: audio, camera, clipboard, dialog, events, filesystem, gamepad, gpu, haptic, hints, init, joystick, keyboard, log, mouse, pen, power, properties, rect, render, sensor, storage, surface, time, timer, touch, video
- Platform: iostream, loadso, locale, messagebox, misc, process, stdinc, system, vulkan
- Specialized: blendmode, error, guid, metal, pixels, scancode
### Intentionally Skipped
- **assert**: Macro-only header (no types to parse)
- **mutex**: Low-level unsafe primitives (use std.Thread.Mutex instead)
- **thread**: Complex concurrency primitives (use std.Thread instead)
- **hidapi**: Low-level USB/HID interface (specialized use)
- **tray**: Platform-specific system tray (incomplete API)
## Known Limitations
### 1. Field Names That Shadow Zig Keywords
**Issue**: Fields named `type`, `error`, `async`, etc. cause compilation errors
**Status**: ✅ **FIXED** - Automatic escaping implemented
**Example**:
```c
typedef struct {
int type; // Automatically escaped now
} SDL_Something;
```
**Generated**:
```zig
pub const Something = extern struct {
@"type": c_int, // Auto-escaped!
};
```
**Keywords Handled**: type, error, async, await, suspend, resume, try, catch, if, else, for, while, switch, return, break, continue, defer, unreachable, noreturn, comptime, inline, export, extern, packed, const, var, fn, pub, test, struct, enum, union, opaque
### 2. Function Pointer Typedefs
**Issue**: Function pointer types generate as opaque types instead of function pointers
**Status**: ✅ **FIXED** - Proper function pointer typedef support implemented
**Example**:
```c
typedef void (*SDL_HitTest)(SDL_Window *window, const SDL_Point *pt, void *data);
```
**Generated**:
```zig
pub const HitTest = *const fn (?*Window, *const Point, ?*anyopaque) callconv(.C) void;
```
**Support**: Full function pointer parsing with parameters, return types, and proper Zig calling convention
### 3. SDL_UINT64_C Macro in Bit Positions
**Issue**: Some 64-bit flag patterns may not parse correctly
**Example**:
```c
#define SDL_WINDOW_FULLSCREEN SDL_UINT64_C(0x0000000000000001)
```
**Status**: Enhanced support added, but not fully tested
**Workaround**: Manual flag definitions if needed
**Priority**: Medium
**Effort**: ~30 minutes validation
**Affected**: SDL_video.h WindowFlags
### 4. External Library Types
**Issue**: Types from external libraries (EGL, OpenGL) not found
**Example**:
```c
SDL_EGLConfig
SDL_EGLDisplay
SDL_GLContext
```
**Status**: Expected behavior (not SDL types)
**Workaround**: Use C imports or manual definitions
**Priority**: N/A (expected)
### 5. Memory Leaks in Comment Handling
**Issue**: Small memory leaks in struct comment parsing
**Status**: ✅ **FIXED** - Proper memory cleanup implemented
**Impact**: None - all allocations properly freed
### 6. Array Field Declarations
**Issue**: Array fields in multi-field syntax not supported
**Example**:
```c
int array1[10], array2[20]; // Not handled
```
**Workaround**: Rare in SDL, can be manually defined
**Priority**: Low
**Effort**: ~1 hour
### 7. Bit Field Declarations
**Issue**: Bit fields not supported
**Example**:
```c
struct {
unsigned a : 4;
unsigned b : 4;
};
```
**Status**: Not used in SDL public API
**Priority**: Very Low
## Workaround Strategies
### Strategy 1: Manual Type Definitions
Create a supplementary file with missing types:
```zig
// manual_types.zig
pub const HitTest = *const fn(?*Window, *const Point, ?*anyopaque) callconv(.C) void;
pub const Scancode = c_int; // Simplified if full enum not needed
```
### Strategy 2: Direct C Import
For problematic types, use C directly:
```zig
const c = @cImport(@cInclude("SDL3/SDL.h"));
pub const Scancode = c.SDL_Scancode;
```
### Strategy 3: Selective Generation
Only generate for headers that work:
```bash
# These work well:
zig build run -- SDL_gpu.h --output=gpu.zig
zig build run -- SDL_properties.h --output=properties.zig
# These need work:
# SDL_keyboard.h, SDL_events.h (use C import for now)
```
## Testing Results
### ✅ Successfully Generated (45+ headers)
All major SDL3 APIs successfully parse and generate working Zig bindings:
**Core**: audio, camera, clipboard, dialog, events, filesystem, gamepad, gpu, haptic, hints, init, joystick, keyboard, log, mouse, pen, power, properties, rect, render, sensor, storage, surface, time, timer, touch, video
**Platform**: iostream, loadso, locale, messagebox, misc, process, stdinc, system, vulkan
**Specialized**: blendmode, error, guid, metal, pixels, scancode
**Coverage**: ~95% of SDL3 public API
## Error Messages Explained
### "Could not find definition for type: X"
**Meaning**: Type referenced but not found in any included header
**Possible Causes**:
1. Type is a function pointer (not supported)
2. Type is external (EGL, GL) (expected)
3. Type is in a header not included
4. Type uses unsupported pattern
**Action**: Check if type is needed, add manually if so
### "Syntax errors detected in generated code"
**Meaning**: Generated Zig code doesn't parse
**Possible Causes**:
1. Large enum parsing issue
2. Field name shadows keyword
3. Unsupported C pattern
**Action**: Check line numbers in error, see if manual fix needed
### "InvalidBitPosition"
**Meaning**: Flag value pattern not recognized
**Possible Causes**:
1. Uses SDL_UINT64_C macro (partially supported)
2. Complex bit expression
3. Non-standard format
**Action**: May need to manually define flags
### Memory Leak Warnings
**Meaning**: Small allocations not freed
**Impact**: Minimal (1-2KB per run)
**Status**: Known issue in comment handling, functional
**Action**: None required (will be fixed in future)
## Supported vs Unsupported
### ✅ Fully Supported
- Opaque types
- Simple structs
- Multi-field structs (`int x, y;`)
- Enums (up to ~100 values)
- Flags (with standard patterns)
- Typedefs (simple type aliases)
- Functions (extern declarations)
- Dependency resolution
- Type conversion
- Method grouping
### ⚠️ Partially Supported
- Large enums (300+ values) - needs work
- SDL_UINT64_C flags - enhanced but not fully tested
- Some bit position patterns
### ❌ Not Supported
- Function pointer typedefs
- #define-based type definitions (without typedef)
- Union types
- Bit field structs
- Complex macro expressions
- Non-SDL types
## Reporting Issues
When encountering a new issue:
1. **Check this document** - May already be known
2. **Test with simple case** - Isolate the problem
3. **Check generated output** - Look at line numbers in errors
4. **Document the pattern** - Save example for future reference
## Future Improvements
### Possible Enhancements
1. **Union support** - Rarely used in SDL (low priority)
2. **Bit field support** - Not in SDL public API (very low priority)
3. **Array field improvements** - Handle complex array patterns (low priority)
4. **Better error messages** - More detailed diagnostics (medium priority)
## Comparison with Manual Approach
### Manual Binding Creation
**Time**: ~30 minutes per header
**Error Rate**: High (missing fields, wrong types)
**Maintenance**: Manual updates needed
**Consistency**: Varies by developer
### Parser Approach
**Time**: ~0.5 seconds
**Error Rate**: Low (for supported patterns)
**Maintenance**: Automatic with SDL updates
**Consistency**: Perfect (deterministic)
**Conclusion**: Parser is vastly superior for supported patterns, with clear workarounds for unsupported cases.
---
**Status**: Production ready - 45+ SDL3 headers successfully generated
**Recommendation**: Use generated bindings for all supported headers
**Next**: See [Development](DEVELOPMENT.md) for extending the parser

View File

@ -1,203 +0,0 @@
# SDL3 Parser - Quick Start Guide
## What It Does
Automatically generates Zig bindings from SDL3 C headers with automatic dependency resolution.
## Installation & Build
```bash
cd parser/
zig build # Build parser executable
zig build test # Run all tests
```
## Basic Usage
### Parse a Header
```bash
# Output to stdout
zig build run -- ../SDL/include/SDL3/SDL_gpu.h
# Output to file
zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=gpu.zig
# Generate with C mocks
zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=gpu.zig --mocks=gpu_mock.c
```
### What It Generates
**Input** (`SDL_gpu.h` excerpt):
```c
typedef struct SDL_GPUDevice SDL_GPUDevice;
extern SDL_DECLSPEC void SDLCALL SDL_DestroyGPUDevice(SDL_GPUDevice *device);
```
**Output** (`gpu.zig`):
```zig
pub const GPUDevice = opaque {
pub inline fn destroyGPUDevice(gpudevice: *GPUDevice) void {
return c.SDL_DestroyGPUDevice(gpudevice);
}
};
```
## Features
### ✅ Supported C Patterns
- **Opaque types**: `typedef struct SDL_Type SDL_Type;`
- **Enums**: `typedef enum { VALUE1, VALUE2 } SDL_Type;`
- **Structs**: `typedef struct { int field; } SDL_Type;`
- **Flags**: Packed bitfield enums
- **Functions**: `extern SDL_DECLSPEC RetType SDLCALL SDL_Func(...);`
### ✅ Automatic Dependency Resolution
- Detects types referenced but not defined
- Searches included headers for definitions
- Automatically includes needed types in output
- Handles: `SDL_FColor`, `SDL_Rect`, `SDL_Window`, `SDL_FlipMode`, etc.
### ✅ Type Conversion
| C Type | Zig Type |
|--------|----------|
| `bool` | `bool` |
| `Uint32` | `u32` |
| `SDL_Type*` | `?*Type` (nullable) |
| `const SDL_Type*` | `*const Type` |
| `void*` | `?*anyopaque` |
| `const char*` | `[*c]const u8` |
### ✅ Naming Conventions
- Strip `SDL_` prefix: `SDL_GPUDevice``GPUDevice`
- Remove first underscore: `SDL_GPU_Type``GPUType`
- camelCase functions: `SDL_CreateDevice``createDevice`
## Current Limitations
### ⚠️ Not Yet Supported
1. **Multi-field structs**: `int x, y;` (parsed as single field)
- **Workaround**: Manually expand or wait for next version
2. **Simple typedefs**: `typedef Uint32 SDL_Type;`
- **Workaround**: Add manually to output
3. **#define constants**: `#define VALUE (1u << 0)`
- **Workaround**: Use clang preprocessor or manual definitions
## Project Structure
```
parser/
├── src/
│ ├── parser.zig # Main entry point
│ ├── patterns.zig # Pattern matching & scanning
│ ├── types.zig # C to Zig type conversion
│ ├── naming.zig # Naming conventions
│ ├── codegen.zig # Zig code generation
│ ├── mock_codegen.zig # C mock generation
│ └── dependency_resolver.zig # Dependency analysis [NEW]
├── test/ # Test files
├── docs/ # Documentation
├── build.zig # Build configuration
└── README.md # Full documentation
```
## Documentation
- `PARSER_OVERVIEW.md` - How the parser works
- `DEPENDENCY_PLAN.md` - Original dependency design
- `DEPENDENCY_IMPLEMENTATION_STATUS.md` - Current status
- `IMPLEMENTATION_SUMMARY.md` - Session summary
- `AGENTS.md` - Zig 0.15 guidelines for AI agents
- `TODO.md` - Next steps
## Testing
```bash
# Run all tests
zig build test
# Test with specific header
zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=test_output.zig
# Verify output compiles (requires c.zig)
zig ast-check test_output.zig
```
## Example Workflow
1. **Parse header with dependencies**:
```bash
zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=gpu.zig
```
2. **Check the output**:
```bash
cat gpu.zig | head -50
```
3. **Create c.zig wrapper**:
```zig
pub const c = @cImport({
@cInclude("SDL3/SDL.h");
});
```
4. **Use in your project**:
```zig
const gpu = @import("gpu.zig");
pub fn main() !void {
const device = gpu.createGPUDevice(true);
defer device.?.destroyGPUDevice();
}
```
## Common Issues
### "FileNotFound" error
- Check header path is correct relative to working directory
- Use absolute path: `/full/path/to/SDL/include/SDL3/SDL_gpu.h`
### "Syntax errors detected"
- Usually multi-field struct issue (known limitation)
- Check output file for specific line numbers
- Manually fix or wait for parser update
### "Warning: Could not find definition for type"
- Type might be typedef (not yet supported)
- Type might be in different include (check manually)
- Type might be #define-based (use manual definition)
## Performance
- Small headers (<100 decls): ~100ms
- Large headers (SDL_gpu.h, 169 decls): ~500ms with dependencies
- Memory usage: ~2-5MB peak
- Output size: ~1KB per declaration
## Getting Help
1. Check `DEPENDENCY_IMPLEMENTATION_STATUS.md` for known issues
2. Look at `TODO.md` for planned improvements
3. Read `AGENTS.md` if you're an AI agent working on this
4. Check test files in `test/` for usage examples
## Version Info
- **Parser Version**: 2.0 (with dependency resolution)
- **Zig Version**: 0.15.2
- **SDL Version**: 3.2.0
- **Status**: Operational with known limitations ✅
---
**Last Updated**: 2026-01-22
**Next Milestone**: Fix multi-field struct parsing