summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMinijackson <minijackson@riseup.net>2023-01-24 22:42:09 +0100
committerMinijackson <minijackson@riseup.net>2023-01-24 22:42:09 +0100
commit5d9e2b87d68c2db57f7851e0e321ded41deceffe (patch)
tree73e709188e3df5c1c7357d0e8eb65f3a9a721b52
parentf1e0807d302174fcec115e5c559d28b1de17849d (diff)
downloaddiaphragm-5d9e2b87d68c2db57f7851e0e321ded41deceffe.tar.gz
diaphragm-5d9e2b87d68c2db57f7851e0e321ded41deceffe.zip
examples/railroad: init grammar diagram
-rw-r--r--examples/railroad.lua347
1 files changed, 347 insertions, 0 deletions
diff --git a/examples/railroad.lua b/examples/railroad.lua
new file mode 100644
index 0000000..8e74441
--- /dev/null
+++ b/examples/railroad.lua
@@ -0,0 +1,347 @@
1package.cpath = package.cpath .. ";../target/debug/?.so"
2package.path = package.path .. ";../lua-bindings/?.lua"
3
4local dia = require("diaphragm")
5
6dia.util.eprint("----------")
7
8local nord_colors = {
9 base00 = "#2E3440",
10 base01 = "#3B4252",
11 base02 = "#434C5E",
12 base03 = "#4C566A",
13 base04 = "#D8DEE9",
14 base05 = "#E5E9F0",
15 base06 = "#ECEFF4",
16 base07 = "#8FBCBB",
17 base08 = "#BF616A",
18 base09 = "#D08770",
19 base0A = "#EBCB8B",
20 base0B = "#A3BE8C",
21 base0C = "#88C0D0",
22 base0D = "#81A1C1",
23 base0E = "#B48EAD",
24 base0F = "#5E81AC",
25}
26
27local function begin(params)
28 local result = dia.shape(params)
29
30 result.icon = dia.rectangle.surrounding(result, {
31 height = 10,
32 width = 10,
33 fill_color = nord_colors.base00,
34 })
35 result.beginning = result.middle_left
36 result.ending = result.middle_right
37
38 function result:draw()
39 self.icon:draw()
40 end
41
42 return result
43end
44
45local function stop(params)
46 return begin(params)
47end
48
49function token(params)
50 local result = dia.shape(params)
51
52 result.name = params.name or "token"
53 result.font = params.font or dia.text.font({ family = "Fira Code", size = 14 * 1024 })
54 result.text = params.text or dia.text.new({
55 content = result.name,
56 font = result.font,
57 })
58
59 result.fill_color = params.fill_color or nord_colors.base04
60 result.padding = params.padding or 5
61 result.box = dia.rectangle.surrounding(result.text, {
62 fill_color = result.fill_color,
63 -- TODO: make that a parameter
64 margin_left = 5,
65 margin_right = 5,
66 margin_top = 2,
67 margin_bottom = 2,
68 })
69 dia.constraint.inset(result.box, result)
70
71 result.beginning = result.box.middle_left
72 result.ending = result.box.middle_right
73
74 function result:draw()
75 self.box:draw()
76 self.text:draw()
77 end
78
79 return result
80end
81
82function optional(params)
83 local result = dia.shape(params)
84
85 result.line_spacing = params.line_spacing or 10
86
87 result.beginning = result.element.beginning - { x = result.line_spacing }
88 result.ending = result.element.ending + { x = result.line_spacing }
89 result.top_left = result.element.top_left - {
90 x = result.line_spacing,
91 y = result.line_spacing,
92 }
93 result.top_right = result.element.top_right + {
94 x = result.line_spacing,
95 y = -result.line_spacing,
96 }
97
98 result.overline = dia.straight_path.new({
99 points = {
100 result.beginning,
101 result.top_left,
102 result.top_right,
103 result.ending,
104 },
105 })
106 result.left_line = dia.straight_path.new({
107 points = { result.beginning, result.element.beginning },
108 })
109 result.right_line = dia.straight_path.new({
110 points = { result.element.ending, result.ending },
111 })
112
113 result.bottom = result.element.bottom
114
115 function result:draw()
116 result.overline:draw()
117 result.left_line:draw()
118 result.right_line:draw()
119 result.element:draw()
120 end
121
122 return result
123end
124
125function choice(params)
126 local result = dia.shape(params)
127
128 result.line_spacing = params.line_spacing or 10
129 result.padding = params.padding or 10
130
131 result.stack = dia.layout.vstack({
132 elements = result.choices,
133 align = "left",
134 top = result.top,
135 bottom = result.bottom,
136 spacing = result.padding,
137 })
138
139 result.beginning = result.choices[1].beginning - { x = result.line_spacing }
140 result.ending = {
141 x = result.stack.right + result.line_spacing,
142 y = result.choices[1].ending.y,
143 }
144
145 result.left_hook = dia.straight_path.new({
146 points = {
147 result.choices[1].beginning,
148 result.beginning,
149 result.choices[#result.choices].beginning - { x = result.line_spacing },
150 result.choices[#result.choices].beginning,
151 },
152 })
153 result.right_hook = dia.straight_path.new({
154 points = {
155 result.choices[1].ending,
156 result.ending,
157 {
158 x = result.ending.x,
159 y = result.choices[#result.choices].ending.y,
160 },
161 result.choices[#result.choices].ending,
162 },
163 })
164
165 result.left_connections = {}
166 result.right_connections = {}
167 for i = 2, #result.choices - 1 do
168 table.insert(
169 result.left_connections,
170 dia.straight_path.new({
171 points = {
172 result.choices[i].beginning - { x = result.line_spacing },
173 result.choices[i].beginning,
174 },
175 })
176 )
177 table.insert(
178 result.right_connections,
179 dia.straight_path.new({
180 points = {
181 result.choices[i].ending,
182 { x = result.ending.x, y = result.choices[i].ending.y },
183 },
184 })
185 )
186 end
187
188 dia.constraint.inset(result.stack, result, {
189 margin_left = result.line_spacing,
190 margin_right = result.line_spacing,
191 })
192
193 function result:draw()
194 result.left_hook:draw()
195 result.right_hook:draw()
196 for _, left_conn in ipairs(self.left_connections) do
197 left_conn:draw()
198 end
199 for _, right_conn in ipairs(self.right_connections) do
200 right_conn:draw()
201 end
202
203 self.stack:draw()
204 end
205
206 return result
207end
208
209function ident(params)
210 return token(dia.util.tbl_extend({
211 fill_color = nord_colors.base0A,
212 }, params))
213end
214
215function typ(params)
216 return token(dia.util.tbl_extend({
217 fill_color = nord_colors.base08,
218 }, params))
219end
220
221function tt(params)
222 return token(dia.util.tbl_extend({
223 fill_color = nord_colors.base0C,
224 }, params))
225end
226
227function connect(params)
228 local result = dia.shape(params)
229
230 result.elements = params.elements or {}
231 result.spacing = params.spacing or 10
232
233 result.beginning = result.elements[1].beginning
234 result.ending = result.elements[#result.elements].ending
235
236 result.stack = dia.layout.hstack({
237 elements = result.elements,
238 align = "none",
239 spacing = result.spacing,
240 })
241 dia.constraint.inset(result.stack, result)
242
243 result.lines = {}
244
245 for i = 1, #result.elements - 1 do
246 local left_el = result.elements[i]
247 local right_el = result.elements[i + 1]
248
249 table.insert(
250 result.lines,
251 dia.straight_path.new({
252 points = { left_el.ending, right_el.beginning },
253 })
254 )
255
256 dia.constrain(left_el.ending.y:eq(right_el.beginning.y))
257 end
258
259 function result:draw()
260 self.stack:draw()
261 for _, line in ipairs(self.lines) do
262 line:draw()
263 end
264 end
265
266 return result
267end
268
269dia.draw({
270 draw = function(self)
271 local figure = connect({
272 elements = {
273 begin(),
274 optional({ element = token({ name = "pub" }) }),
275 ident({ name = "name" }),
276 token({ name = "&lt;" }),
277 typ({ name = "a" }),
278 choice({
279 choices = {
280 connect({
281 elements = {
282 token({ name = "," }),
283 choice({
284 choices = {
285 connect({
286 elements = {
287 typ({ name = "i" }),
288 token({ name = "," }),
289 typ({ name = "o" }),
290 optional({
291 element = connect({
292 elements = {
293 token({ name = "," }),
294 typ({ name = "e" }),
295 },
296 }),
297 }),
298 },
299 }),
300 typ({ name = "o" }),
301 },
302 }),
303 token({ name = ">" }),
304 },
305 }),
306 connect({
307 elements = {
308 token({ name = ">" }),
309 optional({
310 element = connect({
311 elements = {
312 token({ name = "(" }),
313 typ({ name = "i" }),
314 token({ name = ")" }),
315 token({ name = "->" }),
316 typ({ name = "o" }),
317 },
318 }),
319 }),
320 },
321 }),
322 },
323 }),
324 token({ name = "," }),
325 optional({ element = token({ name = "mut" }) }),
326 ident({ name = "self_" }),
327 token({ name = "," }),
328 ident({ name = "submac" }),
329 token({ name = "!" }),
330 token({ name = "(" }),
331 optional({ element = tt({ name = "args" }) }),
332 token({ name = ")" }),
333 stop(),
334 },
335 center = self.center,
336 })
337 dia.rectangle
338 .surrounding(self, {
339 fill_color = nord_colors.base06,
340 stroke_width = 0,
341 })
342 :draw()
343 figure:draw()
344 dia.constraint.inset(figure, self, { margin = 20 })
345 end,
346 output = {},
347})