diff options
author | Minijackson <minijackson@riseup.net> | 2023-01-24 22:42:09 +0100 |
---|---|---|
committer | Minijackson <minijackson@riseup.net> | 2023-01-24 22:42:09 +0100 |
commit | 5d9e2b87d68c2db57f7851e0e321ded41deceffe (patch) | |
tree | 73e709188e3df5c1c7357d0e8eb65f3a9a721b52 /examples | |
parent | f1e0807d302174fcec115e5c559d28b1de17849d (diff) | |
download | diaphragm-5d9e2b87d68c2db57f7851e0e321ded41deceffe.tar.gz diaphragm-5d9e2b87d68c2db57f7851e0e321ded41deceffe.zip |
examples/railroad: init grammar diagram
Diffstat (limited to 'examples')
-rw-r--r-- | examples/railroad.lua | 347 |
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 @@ | |||
1 | package.cpath = package.cpath .. ";../target/debug/?.so" | ||
2 | package.path = package.path .. ";../lua-bindings/?.lua" | ||
3 | |||
4 | local dia = require("diaphragm") | ||
5 | |||
6 | dia.util.eprint("----------") | ||
7 | |||
8 | local 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 | |||
27 | local 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 | ||
43 | end | ||
44 | |||
45 | local function stop(params) | ||
46 | return begin(params) | ||
47 | end | ||
48 | |||
49 | function 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 | ||
80 | end | ||
81 | |||
82 | function 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 | ||
123 | end | ||
124 | |||
125 | function 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 | ||
207 | end | ||
208 | |||
209 | function ident(params) | ||
210 | return token(dia.util.tbl_extend({ | ||
211 | fill_color = nord_colors.base0A, | ||
212 | }, params)) | ||
213 | end | ||
214 | |||
215 | function typ(params) | ||
216 | return token(dia.util.tbl_extend({ | ||
217 | fill_color = nord_colors.base08, | ||
218 | }, params)) | ||
219 | end | ||
220 | |||
221 | function tt(params) | ||
222 | return token(dia.util.tbl_extend({ | ||
223 | fill_color = nord_colors.base0C, | ||
224 | }, params)) | ||
225 | end | ||
226 | |||
227 | function 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 | ||
267 | end | ||
268 | |||
269 | dia.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 = "<" }), | ||
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 | }) | ||