diagramo 0.2.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,479 @@
1
+ Here’s a clean **Diagramo surface-language grammar spec** for the user-friendly lispy language that compiles to NCF.
2
+
3
+ ## Diagramo grammar
4
+
5
+ Diagramo is a small lispy language with two main forms:
6
+
7
+ * **tree forms** for nodes and parent/child structure
8
+ * **arrow forms** for arrows between nodes
9
+
10
+ A document may be either:
11
+
12
+ * a sequence of forms, or
13
+ * wrapped in a top-level `(diagramo ...)`
14
+
15
+ ## EBNF
16
+
17
+ ```ebnf
18
+ document = { ws_or_comment , form } , ws_or_comment
19
+ | "(" , "diagramo" , { ws_or_comment , form } , ws_or_comment , ")" ;
20
+
21
+ form = tree_form | arrow_form ;
22
+
23
+ tree_form = "(" , ws ,
24
+ node_ref ,
25
+ { ws , tree_item } ,
26
+ ws , ")" ;
27
+
28
+ tree_item = node_ref | tree_form ;
29
+
30
+ arrow_form = "(" , ws ,
31
+ "->" , ws ,
32
+ edge_ref , ws ,
33
+ endpoint , ws ,
34
+ endpoint ,
35
+ ws , ")" ;
36
+
37
+ endpoint = node_ref | vector ;
38
+
39
+ vector = "[" , ws ,
40
+ node_ref ,
41
+ { ws , node_ref } ,
42
+ ws , "]" ;
43
+
44
+ node_ref = symbol | labeled_symbol ;
45
+ edge_ref = symbol | labeled_symbol ;
46
+
47
+ labeled_symbol = symbol , "{" , label_text , "}" ;
48
+
49
+ label_text = quoted_string | bare_label ;
50
+
51
+ symbol = initial_char , { symbol_char } ;
52
+
53
+ initial_char = letter | "_" ;
54
+ symbol_char = letter | digit | "_" | "-" | "." ;
55
+
56
+ bare_label = { any_char_except_brace_or_newline } ;
57
+
58
+ quoted_string = '"' , { string_char } , '"' ;
59
+
60
+ string_char = any_char_except_quote_or_backslash
61
+ | "\" , '"'
62
+ | "\" , "\"
63
+ | "\" , "n"
64
+ | "\" , "t" ;
65
+
66
+ ws = { " " | "\t" | "\r" | "\n" } ;
67
+ comment = ";" , { any_char_except_newline } ;
68
+ ws_or_comment = ws | comment ;
69
+ ```
70
+
71
+ ## Meaning of each form
72
+
73
+ ### 1. Node declaration
74
+
75
+ ```diagramo
76
+ (P)
77
+ ```
78
+
79
+ Ensures node `P` exists.
80
+
81
+ Default label is the node id, so this behaves like:
82
+
83
+ * id = `P`
84
+ * label = `P`
85
+
86
+ Example:
87
+
88
+ ```diagramo
89
+ (A)
90
+ (B)
91
+ ```
92
+
93
+ Creates two nodes: `A`, `B`.
94
+
95
+ ---
96
+
97
+ ### 2. Node with label
98
+
99
+ ```diagramo
100
+ (P{hi})
101
+ ```
102
+
103
+ Ensures node `P` exists with label `hi`.
104
+
105
+ Example:
106
+
107
+ ```diagramo
108
+ (P{Person})
109
+ (Q{"Hello world"})
110
+ ```
111
+
112
+ Creates:
113
+
114
+ * node `P` labeled `Person`
115
+ * node `Q` labeled `Hello world`
116
+
117
+ Use quotes when the label contains spaces.
118
+
119
+ ---
120
+
121
+ ### 3. Parent with children
122
+
123
+ ```diagramo
124
+ (X Y Z)
125
+ ```
126
+
127
+ Means:
128
+
129
+ * `X` exists
130
+ * `Y` exists and is a child of `X`
131
+ * `Z` exists and is a child of `X`
132
+
133
+ Example:
134
+
135
+ ```diagramo
136
+ (Folder File1 File2)
137
+ ```
138
+
139
+ `Folder` is the container, `File1` and `File2` are inside it.
140
+
141
+ ---
142
+
143
+ ### 4. Nested parent structure
144
+
145
+ ```diagramo
146
+ (X Y (Z P))
147
+ ```
148
+
149
+ Means:
150
+
151
+ * `Y` is a child of `X`
152
+ * `Z` is a child of `X`
153
+ * `P` is a child of `Z`
154
+
155
+ Example:
156
+
157
+ ```diagramo
158
+ (App Header (Body Sidebar))
159
+ ```
160
+
161
+ This gives:
162
+
163
+ * `Header` inside `App`
164
+ * `Body` inside `App`
165
+ * `Sidebar` inside `Body`
166
+
167
+ ---
168
+
169
+ ### 5. Chained nesting
170
+
171
+ ```diagramo
172
+ (X (Y (Z P)))
173
+ ```
174
+
175
+ Means:
176
+
177
+ * `Y` is a child of `X`
178
+ * `Z` is a child of `Y`
179
+ * `P` is a child of `Z`
180
+
181
+ Example:
182
+
183
+ ```diagramo
184
+ (World (Continent (Country City)))
185
+ ```
186
+
187
+ This creates a straight nesting chain.
188
+
189
+ ---
190
+
191
+ ### 6. Arrow between two nodes
192
+
193
+ ```diagramo
194
+ (-> e A B)
195
+ ```
196
+
197
+ Creates arrow `e` from `A` to `B`.
198
+
199
+ If `A` or `B` do not already exist, they are created automatically.
200
+
201
+ Example:
202
+
203
+ ```diagramo
204
+ (-> f Login Dashboard)
205
+ ```
206
+
207
+ Creates:
208
+
209
+ * node `Login`
210
+ * node `Dashboard`
211
+ * arrow `f` from `Login` to `Dashboard`
212
+
213
+ ---
214
+
215
+ ### 7. Arrow with label
216
+
217
+ ```diagramo
218
+ (-> e{hi} A B)
219
+ ```
220
+
221
+ Creates arrow `e` from `A` to `B` with label `hi`.
222
+
223
+ Example:
224
+
225
+ ```diagramo
226
+ (-> auth{"sign in"} User Session)
227
+ ```
228
+
229
+ Creates arrow `auth` labeled `sign in`.
230
+
231
+ ---
232
+
233
+ ### 8. Fan-out arrow
234
+
235
+ ```diagramo
236
+ (-> e A [B C D])
237
+ ```
238
+
239
+ Means one source, many targets.
240
+
241
+ This expands to multiple arrows:
242
+
243
+ * `e_1` from `A` to `B`
244
+ * `e_2` from `A` to `C`
245
+ * `e_3` from `A` to `D`
246
+
247
+ Example:
248
+
249
+ ```diagramo
250
+ (-> send Server [Client1 Client2 Client3])
251
+ ```
252
+
253
+ ---
254
+
255
+ ### 9. Fan-in arrow
256
+
257
+ ```diagramo
258
+ (-> e [A B C] D)
259
+ ```
260
+
261
+ Means many sources, one target.
262
+
263
+ This expands to:
264
+
265
+ * `e_1` from `A` to `D`
266
+ * `e_2` from `B` to `D`
267
+ * `e_3` from `C` to `D`
268
+
269
+ Example:
270
+
271
+ ```diagramo
272
+ (-> collect [Sensor1 Sensor2 Sensor3] Database)
273
+ ```
274
+
275
+ ---
276
+
277
+ ## Full examples
278
+
279
+ ### Minimal document
280
+
281
+ ```diagramo
282
+ (A)
283
+ (B)
284
+ (-> f A B)
285
+ ```
286
+
287
+ ### With grouping
288
+
289
+ ```diagramo
290
+ (App Header Footer)
291
+ (App (Main Sidebar))
292
+ (-> nav Header Main)
293
+ (-> info Sidebar Footer)
294
+ ```
295
+
296
+ ### With top-level wrapper
297
+
298
+ ```diagramo
299
+ (diagramo
300
+ (A{Start})
301
+ (B{End})
302
+ (-> flow A B))
303
+ ```
304
+
305
+ ### Mixed hierarchy and arrows
306
+
307
+ ```diagramo
308
+ (diagramo
309
+ (System
310
+ API
311
+ (UI Button Panel)
312
+ (DB Table))
313
+
314
+ (-> req UI API)
315
+ (-> read API DB)
316
+ (-> write API DB)
317
+ (-> click Button API))
318
+ ```
319
+
320
+ ### Fan-out and fan-in
321
+
322
+ ```diagramo
323
+ (diagramo
324
+ (Hub)
325
+ (A)
326
+ (B)
327
+ (C)
328
+ (D)
329
+
330
+ (-> out Hub [A B C])
331
+ (-> in [A B C] D))
332
+ ```
333
+
334
+ ---
335
+
336
+ ## Semantic rules
337
+
338
+ These are the intended compile-time rules.
339
+
340
+ ### Auto-creation
341
+
342
+ Any node mentioned in a tree or arrow form is created if it does not already exist.
343
+
344
+ Example:
345
+
346
+ ```diagramo
347
+ (-> f X Y)
348
+ ```
349
+
350
+ Creates `X` and `Y` automatically.
351
+
352
+ ### Labels
353
+
354
+ A node or arrow may be given a label with `{...}`.
355
+
356
+ Example:
357
+
358
+ ```diagramo
359
+ (A{Alpha})
360
+ (-> e{"goes to"} A B)
361
+ ```
362
+
363
+ If no label is provided, the id is used as the default label.
364
+
365
+ ### Unique ids
366
+
367
+ Node ids must be unique among nodes.
368
+ Arrow ids must be unique among arrows.
369
+
370
+ Fan expansion reserves generated ids like:
371
+
372
+ ```diagramo
373
+ e_1
374
+ e_2
375
+ e_3
376
+ ```
377
+
378
+ ### Parenting
379
+
380
+ A node may have at most one parent.
381
+
382
+ This is valid:
383
+
384
+ ```diagramo
385
+ (X Y)
386
+ ```
387
+
388
+ This should be rejected:
389
+
390
+ ```diagramo
391
+ (X Y)
392
+ (Z Y)
393
+ ```
394
+
395
+ because `Y` would have two parents.
396
+
397
+ ### Repeated references
398
+
399
+ Referring to the same node multiple times is allowed.
400
+
401
+ Example:
402
+
403
+ ```diagramo
404
+ (A)
405
+ (-> f A B)
406
+ (-> g B A)
407
+ ```
408
+
409
+ ### Conflicting labels
410
+
411
+ This should be treated as an error:
412
+
413
+ ```diagramo
414
+ (A{One})
415
+ (A{Two})
416
+ ```
417
+
418
+ because node `A` gets two different labels.
419
+
420
+ ---
421
+
422
+ ## Lexical notes
423
+
424
+ ### Comments
425
+
426
+ A semicolon starts a comment to the end of the line.
427
+
428
+ ```diagramo
429
+ ; this is a comment
430
+ (A)
431
+ (-> f A B) ; inline comment
432
+ ```
433
+
434
+ ### Whitespace
435
+
436
+ Whitespace is ignored except as a separator.
437
+
438
+ So these are equivalent:
439
+
440
+ ```diagramo
441
+ (A B C)
442
+ ```
443
+
444
+ ```diagramo
445
+ (
446
+ A
447
+ B
448
+ C
449
+ )
450
+ ```
451
+
452
+ ### Reserved tokens
453
+
454
+ These should be reserved:
455
+
456
+ * `diagramo`
457
+ * `->`
458
+
459
+ ### Labels with spaces
460
+
461
+ Prefer quoted labels when they contain spaces:
462
+
463
+ ```diagramo
464
+ (Node{"Hello world"})
465
+ (-> e{"edge label"} A B)
466
+ ```
467
+
468
+ ---
469
+
470
+ ## Practical summary
471
+
472
+ The language has only four ideas:
473
+
474
+ * `(A)` → create a node
475
+ * `(A B C)` → make `B` and `C` children of `A`
476
+ * `(-> e A B)` → create an arrow from `A` to `B`
477
+ * `[A B C]` inside an arrow → fan-in or fan-out
478
+
479
+ If you want, I can next turn this into a package-ready `GRAMMAR.md` file.