Skip to content

Commit 089bd54

Browse files
committed
docs: Fix DSL chapter to use correct ZynPEG semantic actions
- Replace invalid "call_runtime" with proper "define"/"commands" syntax - Add @Builtin blocks to map DSL names to ZRTL symbols (like haxe.zyn) - Use actual ZynPEG commands: get_child, get_all_children, get_text, etc. - Fix markdown lint: add language hints to fenced code blocks - Add blank lines around lists per markdown style
1 parent 867dd4b commit 089bd54

1 file changed

Lines changed: 89 additions & 33 deletions

File tree

book/15-building-dsls.md

Lines changed: 89 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ Traditional DSL approaches have trade-offs:
6060

6161
Leverage `zrtl_paint` and `zrtl_window` to create a Processing/p5.js-style creative coding language:
6262

63-
```
63+
```text
6464
// sketch.art - Creative coding DSL
6565
6666
canvas 800 600
@@ -89,26 +89,50 @@ line 0 550 800 550
8989
entry_point: "sketch_main"
9090
}
9191
92+
// Map DSL builtins to ZRTL symbols
93+
@builtin {
94+
canvas_create: "$Paint$canvas_create",
95+
fill_circle: "$Paint$fill_circle",
96+
fill_rect: "$Paint$fill_rect",
97+
set_color: "$Paint$rgb",
98+
}
99+
92100
canvas_stmt = { "canvas" ~ integer ~ integer }
93101
-> TypedStatement {
94-
"call_runtime": "$Paint$canvas_create",
95-
"args": ["$1", "$2"],
96-
"store_result": "canvas"
102+
"commands": [
103+
{ "define": "var_decl", "args": {
104+
"name": "canvas",
105+
"value": { "define": "call", "args": {
106+
"callee": "canvas_create",
107+
"args": ["$1", "$2"]
108+
}}
109+
}}
110+
]
97111
}
98112
99113
fill_stmt = { "fill" ~ color }
100114
-> TypedStatement {
101-
"call_runtime": "$Paint$set_fill_color",
102-
"args": ["canvas", "$color"]
115+
"commands": [
116+
{ "define": "var_decl", "args": {
117+
"name": "fill_color",
118+
"value": "$1"
119+
}}
120+
]
103121
}
104122
105123
circle_stmt = { "circle" ~ expr ~ expr ~ expr }
106124
-> TypedStatement {
107-
"call_runtime": "$Paint$fill_circle",
108-
"args": ["canvas", "$1", "$2", "$3", "fill_color"]
125+
"commands": [
126+
{ "define": "call", "args": {
127+
"callee": "fill_circle",
128+
"args": ["canvas", "$1", "$2", "$3", "fill_color"]
129+
}}
130+
]
109131
}
110132
```
111133

134+
The grammar builds TypedAST nodes (`var_decl`, `call`) that reference `@builtin` symbols. During compilation, these resolve to ZRTL plugin functions like `$Paint$fill_circle`.
135+
112136
**Running the DSL:**
113137

114138
```rust
@@ -138,7 +162,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
138162

139163
Create a language for ETL and data transformation:
140164

141-
```
165+
```text
142166
// pipeline.flow - Data transformation DSL
143167
144168
source "data/sales.csv" as sales
@@ -164,6 +188,7 @@ output "reports/summary.json"
164188
```
165189

166190
**Leveraging ZRTL plugins:**
191+
167192
- `zrtl_fs` for file I/O
168193
- `zrtl_json` for JSON parsing/generation
169194
- `zrtl_string` for text manipulation
@@ -173,7 +198,7 @@ output "reports/summary.json"
173198

174199
A simplified HDL for education or prototyping:
175200

176-
```
201+
```text
177202
// counter.hdl - Hardware description
178203
179204
module counter(clk: clock, reset: bit, out: bits[8]) {
@@ -195,7 +220,7 @@ module counter(clk: clock, reset: bit, out: bits[8]) {
195220

196221
A language for game logic with built-in entity/component concepts:
197222

198-
```
223+
```text
199224
// player.game - Game entity script
200225
201226
entity Player {
@@ -217,6 +242,7 @@ entity Player {
217242
```
218243

219244
**Runtime using ZRTL:**
245+
220246
- `zrtl_window` for windowing/input
221247
- `zrtl_paint` for 2D rendering
222248
- `zrtl_image` for sprite loading
@@ -226,7 +252,7 @@ entity Player {
226252

227253
A type-safe configuration language:
228254

229-
```
255+
```text
230256
// app.config - Typed configuration
231257
232258
database {
@@ -268,59 +294,89 @@ Let's build a simple **charting DSL** that generates visualizations:
268294
entry_point: "render_chart"
269295
}
270296
297+
// Map builtins to chart plugin symbols
298+
@builtin {
299+
chart_set_type: "$Chart$set_type",
300+
chart_set_title: "$Chart$set_title",
301+
chart_add_data: "$Chart$add_data",
302+
chart_set_style: "$Chart$set_style",
303+
chart_render: "$Chart$render",
304+
}
305+
271306
// Entry point
272307
program = { SOI ~ chart_definition ~ EOI }
273-
-> TypedModule {
274-
"create_main": "render_chart",
275-
"body": "$chart_definition"
308+
-> TypedProgram {
309+
"get_child": { "index": 0 }
276310
}
277311
278312
chart_definition = { chart_type ~ title? ~ data_section ~ style_section? }
279-
-> TypedFunction {
280-
"name": "render_chart",
281-
"body": ["$chart_type", "$title", "$data_section", "$style_section"]
313+
-> TypedDeclaration {
314+
"commands": [
315+
{ "define": "function", "args": {
316+
"name": "render_chart",
317+
"params": [],
318+
"return_type": "void",
319+
"body": { "get_all_children": true }
320+
}}
321+
]
282322
}
283323
284324
chart_type = { ("bar" | "line" | "pie") ~ "chart" }
285325
-> TypedStatement {
286-
"call_runtime": "$Chart$set_type",
287-
"args": ["$1"]
326+
"commands": [
327+
{ "define": "call", "args": {
328+
"callee": "chart_set_type",
329+
"args": [{ "get_text": true }]
330+
}}
331+
]
288332
}
289333
290334
title = { "title" ~ string_literal }
291335
-> TypedStatement {
292-
"call_runtime": "$Chart$set_title",
293-
"args": ["$string_literal"]
336+
"commands": [
337+
{ "define": "call", "args": {
338+
"callee": "chart_set_title",
339+
"args": ["$1"]
340+
}}
341+
]
294342
}
295343
296344
data_section = { "data" ~ "{" ~ data_point* ~ "}" }
297345
-> TypedBlock {
298-
"statements": "$data_point"
346+
"get_all_children": true
299347
}
300348
301349
data_point = { string_literal ~ ":" ~ number }
302350
-> TypedStatement {
303-
"call_runtime": "$Chart$add_data",
304-
"args": ["$string_literal", "$number"]
351+
"commands": [
352+
{ "define": "call", "args": {
353+
"callee": "chart_add_data",
354+
"args": ["$1", "$2"]
355+
}}
356+
]
305357
}
306358
307359
style_section = { "style" ~ "{" ~ style_prop* ~ "}" }
308360
-> TypedBlock {
309-
"statements": "$style_prop"
361+
"get_all_children": true
310362
}
311363
312364
style_prop = { identifier ~ ":" ~ (color | number | string_literal) }
313365
-> TypedStatement {
314-
"call_runtime": "$Chart$set_style",
315-
"args": ["$identifier", "$2"]
366+
"commands": [
367+
{ "define": "call", "args": {
368+
"callee": "chart_set_style",
369+
"args": ["$1", "$2"]
370+
}}
371+
]
316372
}
317373
318374
// Terminals
319375
string_literal = @{ "\"" ~ (!"\"" ~ ANY)* ~ "\"" }
320-
-> String { "get_text": true, "trim_quotes": true }
376+
-> String { "get_text": true }
321377
322378
number = @{ "-"? ~ ASCII_DIGIT+ ~ ("." ~ ASCII_DIGIT+)? }
323-
-> Number { "get_text": true, "parse_float": true }
379+
-> Number { "parse_float": true }
324380
325381
color = @{ "#" ~ ASCII_HEX_DIGIT{6} }
326382
-> Color { "get_text": true }
@@ -425,7 +481,7 @@ zrtl_plugin! {
425481

426482
### Step 3: Write DSL Programs
427483

428-
```
484+
```text
429485
// sales_report.chart
430486
431487
bar chart
@@ -536,7 +592,7 @@ zrtl_plugin! {
536592
}
537593
```
538594

539-
```
595+
```text
540596
// In your DSL
541597
user = App.get_user()
542598
if user.is_admin {
@@ -574,7 +630,7 @@ Don't reinvent the wheel. ZRTL provides:
574630

575631
Your DSL syntax should be intuitive for domain experts:
576632

577-
```
633+
```text
578634
// Good: Reads like natural language
579635
send email to "[email protected]" with subject "Hello"
580636

0 commit comments

Comments
 (0)