Skip to content

Commit 48d2af7

Browse files
committed
feat: Add struct/enum declaration grammar rules and placeholder runtime
- Add struct declaration rule: const Point = struct { x: i32, y: i32 }; - Add enum declaration rule: const Color = enum { Red, Green, Blue }; - Add field and variant rules with proper JSON commands - Add placeholder runtime implementations for struct/enum/field/variant - Add RuntimeHost trait methods for struct/enum creation
1 parent 5416a7f commit 48d2af7

2 files changed

Lines changed: 149 additions & 1 deletion

File tree

crates/zyn_peg/grammars/zig.zyn

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,59 @@ program = { SOI ~ declaration* ~ EOI }
2626
]
2727
}
2828

29-
declaration = { fn_decl | const_decl | var_decl }
29+
declaration = { struct_decl | enum_decl | fn_decl | const_decl | var_decl }
3030
-> TypedDeclaration {
3131
"get_child": { "index": 0 }
3232
}
3333

34+
// ===== Struct Declaration =====
35+
36+
struct_decl = { "const" ~ identifier ~ "=" ~ "struct" ~ "{" ~ struct_fields? ~ "}" ~ ";" }
37+
-> TypedDeclaration {
38+
"commands": [
39+
{ "define": "struct", "args": {
40+
"name": "$1",
41+
"fields": "$2"
42+
}}
43+
]
44+
}
45+
46+
struct_fields = { struct_field ~ ("," ~ struct_field)* ~ ","? }
47+
-> List {
48+
"get_all_children": true
49+
}
50+
51+
struct_field = { identifier ~ ":" ~ type_expr }
52+
-> TypedField {
53+
"commands": [
54+
{ "define": "field", "args": { "name": "$1", "type": "$2" } }
55+
]
56+
}
57+
58+
// ===== Enum Declaration =====
59+
60+
enum_decl = { "const" ~ identifier ~ "=" ~ "enum" ~ "{" ~ enum_variants? ~ "}" ~ ";" }
61+
-> TypedDeclaration {
62+
"commands": [
63+
{ "define": "enum", "args": {
64+
"name": "$1",
65+
"variants": "$2"
66+
}}
67+
]
68+
}
69+
70+
enum_variants = { enum_variant ~ ("," ~ enum_variant)* ~ ","? }
71+
-> List {
72+
"get_all_children": true
73+
}
74+
75+
enum_variant = { identifier }
76+
-> TypedVariant {
77+
"get_text": true,
78+
"define": "variant",
79+
"args": { "name": "$result" }
80+
}
81+
3482
// ===== Function Declaration =====
3583

3684
// Split into two rules to handle the optional params correctly

crates/zyn_peg/src/runtime.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,20 @@ pub trait AstHostFunctions {
359359
/// Create a named/user type
360360
fn create_named_type(&mut self, name: &str) -> NodeHandle;
361361

362+
// ========== Struct/Enum Declarations ==========
363+
364+
/// Create a struct declaration
365+
fn create_struct(&mut self, name: &str, fields: Vec<NodeHandle>) -> NodeHandle;
366+
367+
/// Create an enum declaration
368+
fn create_enum(&mut self, name: &str, variants: Vec<NodeHandle>) -> NodeHandle;
369+
370+
/// Create a struct field
371+
fn create_field(&mut self, name: &str, ty: NodeHandle) -> NodeHandle;
372+
373+
/// Create an enum variant
374+
fn create_variant(&mut self, name: &str) -> NodeHandle;
375+
362376
// ========== Span/Location ==========
363377

364378
/// Set span on a node
@@ -1305,6 +1319,30 @@ impl AstHostFunctions for TypedAstBuilder {
13051319
self.alloc_handle()
13061320
}
13071321

1322+
fn create_struct(&mut self, _name: &str, _fields: Vec<NodeHandle>) -> NodeHandle {
1323+
// TODO: Implement struct declaration once TypedDeclaration supports it
1324+
// For now, just allocate a handle
1325+
self.alloc_handle()
1326+
}
1327+
1328+
fn create_enum(&mut self, _name: &str, _variants: Vec<NodeHandle>) -> NodeHandle {
1329+
// TODO: Implement enum declaration once TypedDeclaration supports it
1330+
// For now, just allocate a handle
1331+
self.alloc_handle()
1332+
}
1333+
1334+
fn create_field(&mut self, _name: &str, _ty: NodeHandle) -> NodeHandle {
1335+
// TODO: Implement field once TypedField is available
1336+
// For now, just allocate a handle
1337+
self.alloc_handle()
1338+
}
1339+
1340+
fn create_variant(&mut self, _name: &str) -> NodeHandle {
1341+
// TODO: Implement variant once TypedEnumVariant is available
1342+
// For now, just allocate a handle
1343+
self.alloc_handle()
1344+
}
1345+
13081346
fn set_span(&mut self, _node: NodeHandle, _start: usize, _end: usize) {
13091347
// Spans are handled inline during node creation
13101348
// This could be extended to update spans if needed
@@ -1844,6 +1882,68 @@ impl<'a, H: AstHostFunctions> CommandInterpreter<'a, H> {
18441882
Ok(RuntimeValue::Node(handle))
18451883
}
18461884

1885+
"struct" => {
1886+
let name = match args.get("name") {
1887+
Some(RuntimeValue::String(s)) => s.clone(),
1888+
_ => "AnonymousStruct".to_string(),
1889+
};
1890+
let fields: Vec<NodeHandle> = match args.get("fields") {
1891+
Some(RuntimeValue::List(list)) => {
1892+
list.iter()
1893+
.filter_map(|v| match v {
1894+
RuntimeValue::Node(h) => Some(*h),
1895+
_ => None,
1896+
})
1897+
.collect()
1898+
}
1899+
_ => vec![],
1900+
};
1901+
let handle = self.host.create_struct(&name, fields);
1902+
Ok(RuntimeValue::Node(handle))
1903+
}
1904+
1905+
"enum" => {
1906+
let name = match args.get("name") {
1907+
Some(RuntimeValue::String(s)) => s.clone(),
1908+
_ => "AnonymousEnum".to_string(),
1909+
};
1910+
let variants: Vec<NodeHandle> = match args.get("variants") {
1911+
Some(RuntimeValue::List(list)) => {
1912+
list.iter()
1913+
.filter_map(|v| match v {
1914+
RuntimeValue::Node(h) => Some(*h),
1915+
_ => None,
1916+
})
1917+
.collect()
1918+
}
1919+
_ => vec![],
1920+
};
1921+
let handle = self.host.create_enum(&name, variants);
1922+
Ok(RuntimeValue::Node(handle))
1923+
}
1924+
1925+
"field" => {
1926+
let name = match args.get("name") {
1927+
Some(RuntimeValue::String(s)) => s.clone(),
1928+
_ => "field".to_string(),
1929+
};
1930+
let ty = match args.get("type") {
1931+
Some(RuntimeValue::Node(h)) => *h,
1932+
_ => self.host.create_primitive_type("i32"),
1933+
};
1934+
let handle = self.host.create_field(&name, ty);
1935+
Ok(RuntimeValue::Node(handle))
1936+
}
1937+
1938+
"variant" => {
1939+
let name = match args.get("name") {
1940+
Some(RuntimeValue::String(s)) => s.clone(),
1941+
_ => "Variant".to_string(),
1942+
};
1943+
let handle = self.host.create_variant(&name);
1944+
Ok(RuntimeValue::Node(handle))
1945+
}
1946+
18471947
"program" => {
18481948
let handle = self.host.create_program();
18491949
// Add declarations from args

0 commit comments

Comments
 (0)