1use mech_core::*;
2use mech_core::nodes::{Kind, Matrix};
3use std::collections::HashMap;
4use colored::Colorize;
5use std::io::{Read, Write, Cursor};
6
7#[derive(Debug, Clone, PartialEq)]
8pub struct Formatter{
9 code: String,
10 identifiers: HashMap<u64, String>,
11 rows: usize,
12 cols: usize,
13 indent: usize,
14 html: bool,
15 nested: bool
16}
17
18
19impl Formatter {
20
21 pub fn new() -> Formatter {
22 Formatter {
23 code: String::new(),
24 identifiers: HashMap::new(),
25 rows: 0,
26 cols: 0,
27 indent: 0,
28 html: false,
29 nested: false,
30 }
31 }
32
33 pub fn format(&mut self, tree: &Program) -> String {
34 self.html = false;
35 self.program(tree)
36 }
37
38 pub fn format_html(&mut self, tree: &Program, style: String) -> String {
39 self.html = true;
40 let formatted_src = self.program(tree);
41 let head = format!(r#"<html>
42 <head>
43 <meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
44 <link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
45 <style>
46 {}
47 </style>
48 </head>
49 <body>"#, style);
50 let foot = format!(r#"
51 <div id = "mech-root"></div>
52 <script type="module">
53 import init, {{WasmMech}} from '/pkg/mech_wasm.js';
54 let wasm_core;
55 async function run() {{
56 await init();
57 wasm_core = new WasmMech();
58 var xhr = new XMLHttpRequest();
59 var codeUrl = `/code${{window.location.pathname}}`;
60 xhr.open('GET', codeUrl, true);
61 xhr.onload = function (e) {{
62 if (xhr.readyState === 4) {{
63 if (xhr.status === 200) {{
64 var src = xhr.responseText;
65 wasm_core.run_program(src);
66 wasm_core.init();
67 }} else {{
68 console.error(xhr.statusText);
69 }}
70 }}
71 }};
72 xhr.onerror = function (e) {{
73 console.error(xhr.statusText);
74 }};
75 xhr.send(null);
76 }}
77 run();
78 </script>
79 </body>
80</html>"#);
81 format!("{}{}{}", head, formatted_src, foot)
82 }
83
84 pub fn program(&mut self, node: &Program) -> String {
85 let title = match &node.title {
86 Some(title) => self.title(&title),
87 None => "".to_string(),
88 };
89 let body = self.body(&node.body);
90 if self.html {
91 format!("<div class=\"mech-program\">{}{}</div>",title,body)
92 } else {
93 format!("{}{}",title,body)
94 }
95 }
96
97 pub fn title(&mut self, node: &Title) -> String {
98 if self.html {
99 format!("<h1 class=\"mech-program-title\">{}</h1>",node.to_string())
100 } else {
101 format!("{}\n===============================================================================\n",node.to_string())
102 }
103 }
104
105 pub fn subtitle(&mut self, node: &Subtitle) -> String {
106 let level = node.level;
107 if self.html {
108 format!("<h{} class=\"mech-program-subtitle\">{}</h{}>", level, node.to_string(), level)
109 } else {
110 format!("{}\n-------------------------------------------------------------------------------\n",node.to_string())
111 }
112 }
113
114 pub fn body(&mut self, node: &Body) -> String {
115 let mut src = "".to_string();
116 let section_count = node.sections.len();
117 for (i, section) in node.sections.iter().enumerate() {
118 let s = self.section(section);
119 src = format!("{}{}", src, s);
120 }
121 if self.html {
122 format!("<div class=\"mech-program-body\">{}</div>",src)
123 } else {
124 src
125 }
126 }
127
128 pub fn section(&mut self, node: &Section) -> String {
129 let mut src = match &node.subtitle {
130 Some(title) => self.subtitle(title),
131 None => "".to_string(),
132 };
133 for el in node.elements.iter() {
134 let el_str = self.section_element(el);
135 src = format!("{}{}", src, el_str);
136 }
137 if self.html {
138 format!("<section class=\"mech-program-section\">{}</section>",src)
139 } else {
140 src
141 }
142 }
143
144 pub fn paragraph(&mut self, node: &Paragraph) -> String {
145 if self.html {
146 format!("<p class=\"mech-paragraph\">{}</p>",node.to_string())
147 } else {
148 format!("{}\n",node.to_string())
149 }
150 }
151
152 pub fn section_element(&mut self, node: &SectionElement) -> String {
153 let element = match node {
154 SectionElement::Section(n) => self.section(n),
155 SectionElement::Comment(n) => self.comment(n),
156 SectionElement::Paragraph(n) => self.paragraph(n),
157 SectionElement::MechCode(n) => self.mech_code(n),
158 SectionElement::UnorderedList(n) => self.unordered_list(n),
159 SectionElement::CodeBlock => todo!(),
160 SectionElement::OrderedList => todo!(),
161 SectionElement::BlockQuote => todo!(),
162 SectionElement::ThematicBreak => todo!(),
163 SectionElement::Image => todo!(),
164 };
165 if self.html {
166 format!("<div class=\"mech-section-element\">{}</div>",element)
167 } else {
168 element
169 }
170 }
171
172 pub fn comment(&mut self, node: &Comment) -> String {
173 if self.html {
174 format!("<div class=\"mech-comment\">-- {}</div>",node.text.to_string())
175 } else {
176 format!("{}\n",node.text.to_string())
177 }
178 }
179
180 pub fn unordered_list(&mut self, node: &UnorderedList) -> String {
181 let mut lis = "".to_string();
182 for (i, item) in node.items.iter().enumerate() {
183 let it = self.paragraph(item);
184 if self.html {
185 lis = format!("{}<li class=\"mech-list-item\">{}</li>",lis,it);
186 } else {
187 lis = format!("{}- {}\n",lis,it);
188 }
189 }
190 if self.html {
191 format!("<ul class=\"mech-unordered-list\">{}</ul>",lis)
192 } else {
193 lis
194 }
195 }
196
197 pub fn mech_code(&mut self, node: &Vec<MechCode>) -> String {
198 let mut src = String::new();
199 for code in node {
200 let c = match code {
201 MechCode::Expression(expr) => self.expression(expr),
202 MechCode::Statement(stmt) => self.statement(stmt),
203 MechCode::FsmSpecification(fsm_spec) => self.fsm_specification(fsm_spec),
204 MechCode::FsmImplementation(fsm_impl) => self.fsm_implementation(fsm_impl),
205 MechCode::Comment(cmnt) => self.comment(cmnt),
206 _ => todo!(),
207 };
209 if self.html {
210 src.push_str(&format!("<div class=\"mech-code\">{}</div>", c));
211 } else {
212 src.push_str(&format!("{}\n", c));
213 }
214 }
215 if self.html {
216 format!("<div class=\"mech-code-block\">{}</div>",src)
217 } else {
218 src
219 }
220 }
221
222 pub fn fsm_implementation(&mut self, node: &FsmImplementation) -> String {
223 let name = node.name.to_string();
224 let mut input = "".to_string();
225 for (i, ident) in node.input.iter().enumerate() {
226 let v = ident.to_string();
227 if i == 0 {
228 input = format!("{}", v);
229 } else {
230 input = format!("{}, {}", input, v);
231 }
232 }
233 let start = self.pattern(&node.start);
234 let mut arms = "".to_string();
235 for (i, arm) in node.arms.iter().enumerate() {
236 let a = self.fsm_arm(arm, i == node.arms.len() - 1);
237 if i == 0 {
238 arms = format!("{}", a);
239 } else {
240 arms = format!("{}{}", arms, a);
241 }
242 }
243 if self.html {
244 format!("<div class=\"mech-fsm-implementation\">
245 <div class=\"mech-fsm-implementation-header\">
246 <span class=\"mech-fsm-sigil\">#</span>
247 <span class=\"mech-fsm-name\">{}</span>
248 <span class=\"mech-left-paren\">(</span>
249 <span class=\"mech-fsm-input\">{}</span>
250 <span class=\"mech-right-paren\">)</span>
251 <span class=\"mech-fsm-define-op\">→</span>
252 <span class=\"mech-fsm-start\">{}</span>
253 </div>
254 <div class=\"mech-fsm-arms\">
255 {}
256 </div>
257 </div>",name,input,start,arms)
258 } else {
259 format!("#{}({}) {} {}\n{}", name, input, "->" , start, arms)
260 }
261 }
262
263 pub fn fsm_arm(&mut self, node: &FsmArm, last: bool) -> String {
264 let arm = match node {
265 FsmArm::Guard(pattern, guards) => {
266 let p = self.pattern(pattern);
267 let mut gs = "".to_string();
268 for (i, guard) in guards.iter().enumerate() {
269 let g = self.guard(guard);
270 if i == 0 {
271 if self.html {
272 gs = format!("<div class=\"mech-fsm-guard-arm\">├ {}</div>", g);
273 } else {
274 gs = format!(" ├ {}\n", g);
275 }
276 } else if i == guards.len() - 1 {
277 if self.html {
278 gs = format!("{}<div class=\"mech-fsm-guard-arm\">└ {}</div>", gs, g);
279 } else {
280 gs = format!("{} └ {}", gs, g);
281 }
282 } else {
283 if self.html {
284 gs = format!("{}<div class=\"mech-fsm-guard-arm\">├ {}</div>", gs, g);
285 } else {
286 gs = format!("{} ├ {}\n", gs, g);
287 }
288 }
289 }
290 if self.html {
291 format!("<div class=\"mech-fsm-arm-guard\">
292 <span class=\"mech-fsm-start\">{}</span>
293 <span class=\"mech-fsm-guards\">{}</span>
294 </div>",p,gs)
295 } else {
296 format!(" {}\n{}", p, gs)
297 }
298 },
299 FsmArm::Transition(pattern, transitions) => {
300 let p = self.pattern(pattern);
301 let mut ts = "".to_string();
302 for (i, transition) in transitions.iter().enumerate() {
303 let t = self.transition(transition);
304 if i == 0 {
305 ts = format!("{}", t);
306 } else {
307 ts = format!("{}{}", ts, t);
308 }
309 }
310 if self.html {
311 format!("<div class=\"mech-fsm-arm\">
312 <span class=\"mech-fsm-arm-pattern\">{}</span>
313 <span class=\"mech-fsm-arm-transitions\">{}</span>
314 </div>",p,ts)
315 } else {
316 format!(" {}{}", p, ts)
317 }
318 },
319 };
320 if self.html {
321 if last {
322 format!("<div class=\"mech-fsm-arm-last\">{}.</div>",arm)
323 } else {
324 format!("<div class=\"mech-fsm-arm\">{}</div>",arm)
325 }
326 } else {
327 if last {
328 format!("{}.", arm)
329 } else {
330 format!("{}\n", arm)
331 }
332 }
333 }
334
335 pub fn guard(&mut self, node: &Guard) -> String {
336 let condition = self.pattern(&node.condition);
337 let mut transitions = "".to_string();
338 for (i, transition) in node.transitions.iter().enumerate() {
339 let t = self.transition(transition);
340 if i == 0 {
341 transitions = format!("{}", t);
342 } else {
343 transitions = format!("{}{}", transitions, t);
344 }
345 }
346 if self.html {
347 format!("<div class=\"mech-guard\">
348 <span class=\"mech-guard-condition\">{}</span>
349 <span class=\"mech-guard-transitions\">{}</span>
350 </div>",condition,transitions)
351 } else {
352 format!("{}{}", condition, transitions)
353 }
354 }
355
356
357 pub fn pattern(&mut self, node: &Pattern) -> String {
358 let p = match node {
359 Pattern::Wildcard => {
360 if self.html {
361 format!("<span class=\"mech-pattern-wildcard\">*</span>")
362 } else {
363 format!("*")
364 }
365 },
366 Pattern::Formula(factor) => self.factor(factor),
367 Pattern::Expression(expr) => self.expression(expr),
368 Pattern::TupleStruct(tuple_struct) => self.pattern_tuple_struct(tuple_struct),
369 };
370 if self.html {
371 format!("<span class=\"mech-pattern\">{}</span>",p)
372 } else {
373 p
374 }
375 }
376
377 pub fn pattern_tuple_struct(&mut self, node: &PatternTupleStruct) -> String {
378 let name = node.name.to_string();
379 let mut patterns = "".to_string();
380 for (i, pattern) in node.patterns.iter().enumerate() {
381 let p = self.pattern(pattern);
382 if i == 0 {
383 patterns = format!("{}", p);
384 } else {
385 patterns = format!("{}, {}", patterns, p);
386 }
387 }
388 if self.html {
389 format!("<span class=\"mech-tuple-struct\">
390 `
391 <span class=\"mech-tuple-struct-name\">{}</span>
392 <span class=\"mech-left-paren\">(</span>
393 <span class=\"mech-tuple-struct-patterns\">{}</span>
394 <span class=\"mech-right-paren\">)</span>
395 </span>",name,patterns)
396 } else {
397 format!("`{}({})", name, patterns)
398 }
399 }
400
401 pub fn transition(&mut self, node: &Transition) -> String {
402 match node {
403 Transition::Next(pattern) => {
404 if self.html {
405 format!("<span class=\"mech-transition-next\">→ {}</span>",self.pattern(pattern))
406 } else {
407 format!(" {} {}", "->", self.pattern(pattern))
408 }
409 }
410 Transition::Output(pattern) => {
411 if self.html {
412 format!("<span class=\"mech-transition-output\">⇒ {}</span>",self.pattern(pattern))
413 } else {
414 format!(" {} {}", "=>", self.pattern(pattern))
415 }
416 }
417 Transition::Async(pattern) => {
418 if self.html {
419 format!("<span class=\"mech-transition-async\">↝ {}</span>",self.pattern(pattern))
420 } else {
421 format!(" {} {}", "~>", self.pattern(pattern))
422
423 }
424 }
425 Transition::Statement(stmt) => {
426 if self.html {
427 format!("<span class=\"mech-transition-statement\">→ {}</span>",self.statement(stmt))
428 } else {
429 format!(" {} {}", "->", self.statement(stmt))
430 }
431 }
432 Transition::CodeBlock(code) => {
433 let mut code_str = "".to_string();
434 let formatted = self.mech_code(code);
435 if self.html {
436 code_str.push_str(&format!("<span class=\"mech-transition-code\">→ {}</span>", formatted));
437 } else {
438 code_str.push_str(&format!(" {} {}", "->", formatted));
439 }
440 code_str
441 }
442 }
443 }
444
445 pub fn fsm_specification(&mut self, node: &FsmSpecification) -> String {
446 let name = node.name.to_string();
447 let mut input = "".to_string();
448 for (i, var) in node.input.iter().enumerate() {
449 let v = self.var(var);
450 if i == 0 {
451 input = format!("{}", v);
452 } else {
453 input = format!("{}, {}", input, v);
454 }
455 }
456 let output = match &node.output {
457 Some(kind) => format!(" {} {}", "⇒", self.kind_annotation(kind)),
458 None => "".to_string(),
459 };
460 let mut states = "".to_string();
461 for (i, state) in node.states.iter().enumerate() {
462 let v = self.state_definition(state);
463 let state_arm = if node.states.len() == 1 {
464 format!("{} {}", "└", v)
465 } else if i == 0 {
466 format!("{} {}", "├", v)
467 } else if i == node.states.len() - 1 {
468 format!("{} {}{}", "└", v, ".")
469 } else {
470 format!("{} {}", "├", v)
471 };
472 if self.html {
473 states = format!("{}<span class=\"mech-fsm-state\">{}</span>",states,state_arm);
474 } else {
475 states = format!("{} {}\n",states,state_arm);
476 }
477 }
478 if self.html {
479 format!("<div class=\"mech-fsm-specification\">
480 <div class=\"mech-fsm-specification-header\">
481 <span class=\"mech-fsm-sigil\">#</span>
482 <span class=\"mech-fsm-name\">{}</span>
483 <span class=\"mech-left-paren\">(</span>
484 <span class=\"mech-fsm-input\">{}</span>
485 <span class=\"mech-right-paren\">)</span>
486 <span class=\"mech-fsm-output\">{}</span>
487 <span class=\"mech-fsm-define-op\">:=</span>
488 </div>
489 <div class=\"mech-fsm-states\">{}</div>
490 </div>",name,input,output,states)
491 } else {
492 format!("#{}({}){} {}\n{}", name, input, output, ":=", states)
493 }
494 }
495
496 pub fn state_definition(&mut self, node: &StateDefinition) -> String {
497 let name = node.name.to_string();
498 let mut state_variables = "".to_string();
499 match &node.state_variables {
500 Some(vars) => {
501 for (i, var) in vars.iter().enumerate() {
502 let v = self.var(var);
503 if i == 0 {
504 state_variables = format!("{}", v);
505 } else {
506 state_variables = format!("{}, {}", state_variables, v);
507 }
508 }
509 },
510 None => {}
511 }
512 if self.html {
513 format!("<div class=\"mech-state-definition\">
514 <span class=\"mech-state-name\">`{}</span>
515 <span class=\"mech-left-paren\">(</span>
516 <span class=\"mech-state-variables\">{}</span>
517 <span class=\"mech-right-paren\">)</span>
518 </div>",name,state_variables)
519 } else {
520 format!("{}({})", name, state_variables)
521 }
522 }
523
524 pub fn variable_define(&mut self, node: &VariableDefine) -> String {
525 let mut mutable = if node.mutable {
526 "~".to_string()
527 } else {
528 "".to_string()
529 };
530 let var = self.var(&node.var);
531 let expression = self.expression(&node.expression);
532 if self.html {
533 format!("<span class=\"mech-variable-define\"><span class=\"mech-variable-mutable\">{}</span>{}<span class=\"mech-variable-assign-op\">:=</span>{}</span>",mutable, var, expression)
534 } else {
535 format!("{}{} {} {}", mutable, var, ":=", expression)
536 }
537 }
538
539 pub fn statement(&mut self, node: &Statement) -> String {
540 let s = match node {
541 Statement::VariableDefine(var_def) => self.variable_define(var_def),
542 Statement::OpAssign(op_asgn) => self.op_assign(op_asgn),
543 Statement::VariableAssign(var_asgn) => self.variable_assign(var_asgn),
544 _ => todo!(),
545 };
549 if self.html {
550 format!("<span class=\"mech-statement\">{}</span>",s)
551 } else {
552 format!("{}", s)
553 }
554 }
555
556 pub fn variable_assign(&mut self, node: &VariableAssign) -> String {
557 let target = self.slice_ref(&node.target);
558 let expression = self.expression(&node.expression);
559 if self.html {
560 format!("<span class=\"mech-variable-assign\">
561 <span class=\"mech-target\">{}</span>
562 <span class=\"mech-assign-op\">=</span>
563 <span class=\"mech-expression\">{}</span>
564 </span>",target,expression)
565 } else {
566 format!("{} = {}", target, expression)
567 }
568 }
569
570 pub fn op_assign(&mut self, node: &OpAssign) -> String {
571 let target = self.slice_ref(&node.target);
572 let op = self.op_assign_op(&node.op);
573 let expression = self.expression(&node.expression);
574 if self.html {
575 format!("<span class=\"mech-op-assign\"><span class=\"mech-target\">{}</span><span class=\"mech-op\">{}</span><span class=\"mech-expression\">{}</span></span>",target,op,expression)
576 } else {
577 format!("{} {} {}", target, op, expression)
578 }
579 }
580
581 pub fn op_assign_op(&mut self, node: &OpAssignOp) -> String {
582 let op = match node {
583 OpAssignOp::Add => "+=".to_string(),
584 OpAssignOp::Sub => "-=".to_string(),
585 OpAssignOp::Mul => "*=".to_string(),
586 OpAssignOp::Div => "/=".to_string(),
587 OpAssignOp::Exp => "^=".to_string(),
588 };
589 if self.html {
590 format!("<span class=\"mech-op-assign-op\">{}</span>",op)
591 } else {
592 format!("{}", op)
593 }
594 }
595
596 pub fn slice_ref(&mut self, node: &SliceRef) -> String {
597 let name = node.name.to_string();
598 let mut subscript = "".to_string();
599 match &node.subscript {
600 Some(subs) => {
601 for sub in subs.iter() {
602 let s = self.subscript(sub);
603 subscript = format!("{}{}", subscript, s);
604 }
605 },
606 None => {},
607 }
608 if self.html {
609 format!("<span class=\"mech-slice-ref\"><span id=\"{}\" class=\"mech-var-name mech-clickable\">{}</span><span class=\"mech-subscript\">{}</span></span>",hash_str(&name),name,subscript)
610 } else {
611 format!("{}{}", name, subscript)
612 }
613 }
614
615 pub fn expression(&mut self, node: &Expression) -> String {
616 let e = match node {
617 Expression::Var(var) => self.var(var),
618 Expression::Formula(factor) => self.factor(factor),
619 Expression::Literal(literal) => self.literal(literal),
620 Expression::Structure(structure) => self.structure(structure),
621 Expression::Slice(slice) => self.slice(slice),
622 Expression::FunctionCall(function_call) => self.function_call(function_call),
623 Expression::Range(range) => self.range_expression(range),
624 _ => todo!(),
625 };
627 if self.html {
628 format!("<span class=\"mech-expression\">{}</span>",e)
629 } else {
630 format!("{}", e)
631 }
632 }
633
634 pub fn range_expression(&mut self, node: &RangeExpression) -> String {
635 let start = self.factor(&node.start);
636 let operator = match &node.operator {
637 RangeOp::Inclusive => "..".to_string(),
638 RangeOp::Exclusive => "..".to_string(),
639 };
640 let terminal = self.factor(&node.terminal);
641 let increment = match &node.increment {
642 Some((op, factor)) => {
643 let o = match op {
644 RangeOp::Inclusive => "=..".to_string(),
645 RangeOp::Exclusive => "..".to_string(),
646 };
647 let f = self.factor(factor);
648 if self.html {
649 format!("<span class=\"mech-range-increment\">{}{}</span>",o,f)
650 } else {
651 format!("{}{}", o, f)
652 }
653 },
654 None => "".to_string(),
655 };
656 if self.html {
657 format!("<span class=\"mech-range-expression\"><span class=\"mech-range-start\">{}</span><span class=\"mech-range-operator\">{}</span><span class=\"mech-range-terminal\">{}</span>{}</span>",start,operator,terminal,increment)
658 } else {
659 format!("{}{}{}{}", start, operator, terminal, increment)
660 }
661 }
662
663 pub fn function_call(&mut self, node: &FunctionCall) -> String {
664 let name = node.name.to_string();
665 let mut args = "".to_string();
666 for (i, arg) in node.args.iter().enumerate() {
667 let a = self.argument(arg);
668 if i == 0 {
669 args = format!("{}", a);
670 } else {
671 args = format!("{}, {}", args, a);
672 }
673 }
674 if self.html {
675 format!("<span class=\"mech-function-call\"><span id=\"{}\" class=\"mech-function-name mech-clickable\">{}</span><span class=\"mech-left-paren\">(</span><span class=\"mech-argument-list\">{}</span><span class=\"mech-right-paren\">)</span></span>",hash_str(&name),name,args)
676 } else {
677 format!("{}({})", name, args)
678 }
679 }
680
681 pub fn argument(&mut self, node: &(Option<Identifier>, Expression)) -> String {
682 let (name, expr) = node;
683 let n = match name {
684 Some(ident) => ident.to_string(),
685 None => "".to_string(),
686 };
687 let e = self.expression(expr);
688 if self.html {
689 format!("<span class=\"mech-argument\"><span class=\"mech-argument-name\">{}</span><span class=\"mech-argument-expression\">{}</span></span>",n,e)
690 } else {
691 format!("{}{}", n, e)
692 }
693 }
694
695 pub fn slice(&mut self, node: &Slice) -> String {
696 let name = node.name.to_string();
697 let mut subscript = "".to_string();
698 for (i, sub) in node.subscript.iter().enumerate() {
699 let s = self.subscript(sub);
700 subscript = format!("{}{}", subscript, s);
701 }
702 if self.html {
703 format!("<span class=\"mech-slice\"><span id=\"{}\" class=\"mech-var-name mech-clickable\">{}</span><span class=\"mech-subscript\">{}</span></span>",hash_str(&name),name,subscript)
704 } else {
705 format!("{}{}", name, subscript)
706 }
707 }
708
709 pub fn subscript(&mut self, node: &Subscript) -> String {
710 match node {
711 Subscript::Bracket(subs) => self.bracket(subs),
712 Subscript::Formula(factor) => self.factor(factor),
713 Subscript::All => self.all(),
714 Subscript::Dot(ident) => self.dot(ident),
715 Subscript::Swizzle(idents) => self.swizzle(idents),
716 Subscript::Range(range) => self.range_expression(range),
717 Subscript::Brace(subs) => self.brace(subs),
718 Subscript::DotInt(real) => self.dot_int(real),
719 }
720 }
721
722 pub fn brace(&mut self, node: &Vec<Subscript>) -> String {
723 let mut src = "".to_string();
724 for (i, sub) in node.iter().enumerate() {
725 let s = self.subscript(sub);
726 if i == 0 {
727 src = format!("{}", s);
728 } else {
729 src = format!("{},{}", src, s);
730 }
731 }
732 if self.html {
733 format!("<span class=\"mech-brace\">{{{}}}</span>",src)
734 } else {
735 format!("{{{}}}",src)
736 }
737 }
738
739 pub fn swizzle(&mut self, node: &Vec<Identifier>) -> String {
740 let mut src = "".to_string();
741 for (i, ident) in node.iter().enumerate() {
742 let s = self.dot(ident);
743 if i == 0 {
744 src = format!("{}", s);
745 } else {
746 src = format!("{},{}", src, s);
747 }
748 }
749 if self.html {
750 format!("<span class=\"mech-swizzle\">{}</span>",src)
751 } else {
752 format!("{}",src)
753 }
754 }
755
756 pub fn dot_int(&mut self, node: &RealNumber) -> String {
757 let node_str = match node {
758 RealNumber::Integer(tkn) => tkn.to_string(),
759 _ => "".to_string(),
760 };
761 if self.html {
762 format!(".<span class=\"mech-dot-int\">{}</span>",node_str)
763 } else {
764 format!(".{}",node_str)
765 }
766 }
767
768 pub fn dot(&mut self, node: &Identifier) -> String {
769 if self.html {
770 format!(".<span class=\"mech-dot\">{}</span>",node.to_string())
771 } else {
772 format!(".{}",node.to_string())
773 }
774 }
775
776 pub fn all(&mut self) -> String {
777 if self.html {
778 format!("<span class=\"mech-all\">:</span>")
779 } else {
780 ":".to_string()
781 }
782 }
783
784 pub fn bracket(&mut self, node: &Vec<Subscript>) -> String {
785 let mut src = "".to_string();
786 for (i, sub) in node.iter().enumerate() {
787 let s = self.subscript(sub);
788 if i == 0 {
789 src = format!("{}", s);
790 } else {
791 src = format!("{},{}", src, s);
792 }
793 }
794 if self.html {
795 format!("<span class=\"mech-bracket\">[{}]</span>",src)
796 } else {
797 format!("[{}]",src)
798 }
799 }
800
801 pub fn structure(&mut self, node: &Structure) -> String {
802 let s = match node {
803 Structure::Matrix(matrix) => self.matrix(matrix),
804 Structure::Record(record) => self.record(record),
805 Structure::Empty => "_".to_string(),
806 Structure::Table(table) => self.table(table),
807 Structure::Tuple(tuple) => self.tuple(tuple),
808 Structure::TupleStruct(tuple_struct) => self.tuple_struct(tuple_struct),
809 Structure::Set(set) => self.set(set),
810 Structure::Map(map) => self.map(map),
811 };
812 if self.html {
813 format!("<span class=\"mech-structure\">{}</span>",s)
814 } else {
815 format!("{}", s)
816 }
817 }
818
819 pub fn map(&mut self, node: &Map) -> String {
820 let mut src = "".to_string();
821 for (i, mapping) in node.elements.iter().enumerate() {
822 let m = self.mapping(mapping);
823 if i == 0 {
824 src = format!("{}", m);
825 } else {
826 src = format!("{}, {}", src, m);
827 }
828 }
829 if self.html {
830 format!("<span class=\"mech-map\"><span class=\"mech-start-brace\">{{</span>{}}}<span class=\"mech-end-brace\">}}</span></span>",src)
831 } else {
832 format!("{{{}}}", src)
833 }
834 }
835
836 pub fn mapping(&mut self, node: &Mapping) -> String {
837 let key = self.expression(&node.key);
838 let value = self.expression(&node.value);
839 if self.html {
840 format!("<span class=\"mech-mapping\"><span class=\"mech-key\">{}</span><span class=\"mech-colon-op\">:</span><span class=\"mech-value\">{}</span></span>",key,value)
841 } else {
842 format!("{}: {}", key, value)
843 }
844 }
845
846 pub fn set(&mut self, node: &Set) -> String {
847 let mut src = "".to_string();
848 for (i, element) in node.elements.iter().enumerate() {
849 let e = self.expression(element);
850 if i == 0 {
851 src = format!("{}", e);
852 } else {
853 src = format!("{}, {}", src, e);
854 }
855 }
856 if self.html {
857 format!("<span class=\"mech-set\"><span class=\"mech-start-brace\">{{</span>{}<span class=\"mech-end-brace\">}}</span></span>",src)
858 } else {
859 format!("{{{}}}", src)
860 }
861 }
862
863 pub fn tuple_struct(&mut self, node: &TupleStruct) -> String {
864 let name = node.name.to_string();
865 let value = self.expression(&node.value);
866 if self.html {
867 format!("<span class=\"mech-tuple-struct\"><span class=\"mech-tuple-struct-name\">{}</span><span class=\"mech-tuple-struct-value\">{}</span></span>",name,value)
868 } else {
869 format!("{}{}", name, value)
870 }
871 }
872
873 pub fn table(&mut self, node: &Table) -> String {
874 let header = self.table_header(&node.header);
875 let mut rows = "".to_string();
876 for (i, row) in node.rows.iter().enumerate() {
877 let r = self.table_row(row);
878 if i == 0 {
879 rows = format!("{}", r);
880 } else {
881 rows = format!("{}{}", rows, r);
882 }
883 }
884 if self.html {
885 format!("<table class=\"mech-table\">{}<tbody class=\"mech-table-body\">{}</tbody></table>",header,rows)
886 } else {
887 format!("{}{}", header, rows)
888 }
889 }
890
891 pub fn table_header(&mut self, node: &TableHeader) -> String {
892 let mut src = "".to_string();
893 for (i, field) in node.iter().enumerate() {
894 let f = self.field(field);
895 if self.html {
896 src = format!("{}<th class=\"mech-table-field\">{}</th>",src, f);
897 } else {
898 src = format!("{}{}",src, f);
899 }
900 }
901 if self.html {
902 format!("<thead class=\"mech-table-header\"><tr>{}</tr></thead>",src)
903 } else {
904 src
905 }
906 }
907
908 pub fn table_row(&mut self, node: &TableRow) -> String {
909 let mut src = "".to_string();
910 for (i, column) in node.columns.iter().enumerate() {
911 let c = self.table_column(column);
912 if i == 0 {
913 src = format!("{}", c);
914 } else {
915 src = format!("{} {}", src, c);
916 }
917 }
918 if self.html {
919 format!("<tr class=\"mech-table-row\">{}</tr>",src)
920 } else {
921 src
922 }
923 }
924
925 pub fn table_column(&mut self, node: &TableColumn) -> String {
926 let element = self.expression(&node.element);
927 if self.html {
928 format!("<td class=\"mech-table-column\">{}</td>",element)
929 } else {
930 element
931 }
932 }
933
934 pub fn field(&mut self, node: &Field) -> String {
935 let name = node.name.to_string();
936 let kind = if let Some(kind) = &node.kind {
937 self.kind_annotation(kind)
938 } else {
939 "".to_string()
940 };
941 if self.html {
942 format!("<div class=\"mech-field\"><span class=\"mech-field-name\">{}</span><span class=\"mech-field-colon-op\">:</span><span class=\"mech-field-kind\">{}</span></div>",name,kind)
943 } else {
944 format!("{}: {}", name, kind)
945 }
946 }
947
948 pub fn tuple(&mut self, node: &Tuple) -> String {
949 let mut src = "".to_string();
950 for (i, element) in node.elements.iter().enumerate() {
951 let e = self.expression(element);
952 if i == 0 {
953 src = format!("{}", e);
954 } else {
955 src = format!("{},{}", src, e);
956 }
957 }
958 if self.html {
959 format!("<span class=\"mech-tuple\"><span class=\"mech-start-paren\">(</span>{})<span class=\"mech-end-paren\">)</span></span>",src)
960 } else {
961 format!("({})", src)
962 }
963 }
964
965 pub fn record(&mut self, node: &Record) -> String {
966 let mut src = "".to_string();
967 for (i, binding) in node.bindings.iter().enumerate() {
968 let b = self.binding(binding);
969 if i == 0 {
970 src = format!("{}", b);
971 } else {
972 src = format!("{}, {}", src, b);
973 }
974 }
975 if self.html {
976 format!("<span class=\"mech-record\"><span class=\"mech-start-brace\">{{</span>{}<span class=\"mech-end-brace\">}}</span></span>",src)
977 } else {
978 format!("{{{}}}",src)
979 }
980 }
981
982 pub fn binding(&mut self, node: &Binding) -> String {
983 let name = node.name.to_string();
984 let value = self.expression(&node.value);
985 if self.html {
986 format!("<span class=\"mech-binding\"><span class=\"mech-binding-name\">{}</span><span class=\"mech-binding-colon-op\">:</span><span class=\"mech-binding-value\">{}</span></span>",name,value)
987 } else {
988 format!("{}: {}", name, value)
989 }
990 }
991
992 pub fn matrix(&mut self, node: &Matrix) -> String {
993 let mut src = "".to_string();
994 if node.rows.len() == 0 {
995 if self.html {
996 return format!("<span class=\"mech-matrix empty\"><span class=\"mech-bracket start\">[</span><span class=\"mech-bracket end\">]</span></span>");
997 } else {
998 return format!("[]");
999 }
1000 }
1001 let column_count = node.rows[0].columns.len(); for col_index in 0..column_count {
1004 let mut column_elements = Vec::new();
1005 for row in &node.rows {
1006 column_elements.push(&row.columns[col_index]);
1007 }
1008 let c = self.matrix_column_elements(&column_elements);
1009
1010 if col_index == 0 {
1011 src = format!("{}", c);
1012 } else {
1013 src = format!("{} {}", src, c);
1014 }
1015 }
1016
1017 if self.html {
1018 format!("<span class=\"mech-matrix\"><span class=\"mech-bracket start\">[</span>{}<span class=\"mech-bracket end\">]</span></span>", src)
1019 } else {
1020 format!("[{}]", src)
1021 }
1022}
1023
1024pub fn matrix_column_elements(&mut self, column_elements: &[&MatrixColumn]) -> String {
1025 let mut src = "".to_string();
1026 for (i, cell) in column_elements.iter().enumerate() {
1027 let c = self.matrix_column(cell);
1028 if i == 0 {
1029 src = format!("{}", c);
1030 } else {
1031 src = format!("{} {}", src, c);
1032 }
1033 }
1034 if self.html {
1035 format!("<div class=\"mech-matrix-column\">{}</div>", src)
1036 } else {
1037 src
1038 }
1039}
1040
1041
1042 pub fn matrix_row(&mut self, node: &MatrixRow) -> String {
1043 let mut src = "".to_string();
1044 for (i, cell) in node.columns.iter().enumerate() {
1045 let c = self.matrix_column(cell);
1046 if i == 0 {
1047 src = format!("{}", c);
1048 } else {
1049 src = format!("{} {}", src, c);
1050 }
1051 }
1052 if self.html {
1053 format!("<div class=\"mech-matrix-row\">{}</div>",src)
1054 } else {
1055 src
1056 }
1057 }
1058
1059 pub fn matrix_column(&mut self, node: &MatrixColumn) -> String {
1060 let element = self.expression(&node.element);
1061 if self.html {
1062 format!("<span class=\"mech-matrix-element\">{}</span>",element)
1063 } else {
1064 element
1065 }
1066 }
1067
1068 pub fn var(&mut self, node: &Var) -> String {
1069 let annotation = if let Some(kind) = &node.kind {
1070 self.kind_annotation(kind)
1071 } else {
1072 "".to_string()
1073 };
1074 if self.html {
1075 format!("<span class=\"mech-var-name mech-clickable\" id=\"{}\">{}</span>{}",hash_str(&node.name.to_string()), node.name.to_string(), annotation)
1076 } else {
1077 format!("{}{}", node.name.to_string(), annotation)
1078 }
1079 }
1080
1081 pub fn kind_annotation(&mut self, node: &KindAnnotation) -> String {
1082 let kind = self.kind(&node.kind);
1083 if self.html {
1084 format!("<span class=\"mech-kind-annotation\"><{}></span>",kind)
1085 } else {
1086 format!("<{}>", kind)
1087 }
1088 }
1089
1090 pub fn kind(&mut self, node: &Kind) -> String {
1091 let annotation = match node {
1092 Kind::Scalar(ident) => ident.to_string(),
1093 Kind::Empty => "_".to_string(),
1094 Kind::Atom(ident) => format!("`{}",ident.to_string()),
1095 Kind::Tuple(kinds) => {
1096 let mut src = "".to_string();
1097 for (i, kind) in kinds.iter().enumerate() {
1098 let k = self.kind(kind);
1099 if i == 0 {
1100 src = format!("{}", k);
1101 } else {
1102 src = format!("{}, {}", src, k);
1103 }
1104 }
1105 format!("({})", src)
1106 },
1107 Kind::Bracket((kinds, literals)) => {
1108 let mut src = "".to_string();
1109 for (i, kind) in kinds.iter().enumerate() {
1110 let k = self.kind(kind);
1111 if i == 0 {
1112 src = format!("{}", k);
1113 } else {
1114 src = format!("{}, {}", src, k);
1115 }
1116 }
1117 let mut src2 = "".to_string();
1118 for (i, literal) in literals.iter().enumerate() {
1119 let l = self.literal(literal);
1120 if i == 0 {
1121 src2 = format!("{}", l);
1122 } else {
1123 src2 = format!("{}, {}", src2, l);
1124 }
1125 }
1126 format!("[{}]:{}", src, src2)
1127 },
1128 Kind::Brace((kinds, literals)) => {
1129 let mut src = "".to_string();
1130 for (i, kind) in kinds.iter().enumerate() {
1131 let k = self.kind(kind);
1132 if i == 0 {
1133 src = format!("{}", k);
1134 } else {
1135 src = format!("{}, {}", src, k);
1136 }
1137 }
1138 let mut src2 = "".to_string();
1139 for (i, literal) in literals.iter().enumerate() {
1140 let l = self.literal(literal);
1141 if i == 0 {
1142 src2 = format!("{}", l);
1143 } else {
1144 src2 = format!("{}, {}", src2, l);
1145 }
1146 }
1147 format!("{{{}}}:{}", src, src2)
1148 },
1149 Kind::Map(kind1, kind2) => {
1150 let k1 = self.kind(kind1);
1151 let k2 = self.kind(kind2);
1152 format!("{}:{}", k1, k2)
1153 },
1154 Kind::Function(input, output) => todo!(),
1155 Kind::Fsm(input, output) => todo!(),
1156 };
1157 if self.html {
1158 format!("<span class=\"mech-kind\">{}</span>",annotation)
1159 } else {
1160 annotation
1161 }
1162 }
1163
1164 pub fn factor(&mut self, node: &Factor) -> String {
1165 let f = match node {
1166 Factor::Term(term) => self.term(term),
1167 Factor::Expression(expr) => self.expression(expr),
1168 Factor::Parenthetical(paren) => {
1169 if self.html {
1170 format!("<span class=\"mech-parenthetical\">({})</span>", self.factor(paren))
1171 } else {
1172 format!("({})", self.factor(&paren))
1173 }
1174 }
1175 Factor::Negate(factor) => {
1176 if self.html {
1177 format!("<span class=\"mech-negate-op\">-</span><span class=\"mech-negate\">{}</span>", self.factor(factor))
1178 } else {
1179 format!("-{}", self.factor(factor))
1180 }
1181 }
1182 Factor::Not(factor) => {
1183 if self.html {
1184 format!("<span class=\"mech-not-op\">¬</span><span class=\"mech-not\">{}</span>", self.factor(factor))
1185 } else {
1186 format!("¬{}", self.factor(factor))
1187 }
1188 }
1189 Factor::Transpose(factor) => {
1190 if self.html {
1191 format!("<span class=\"mech-transpose\">{}</span><span class=\"mech-transpose-op\">'</span>", self.factor(factor))
1192 } else {
1193 format!("{}'", self.factor(factor))
1194 }
1195 }
1196 };
1197 if self.html {
1198 format!("<span class=\"mech-factor\">{}</span>",f)
1199 } else {
1200 f
1201 }
1202 }
1203
1204 pub fn term(&mut self, node: &Term) -> String {
1205 let mut src = self.factor(&node.lhs);
1206 for (formula_operator, rhs) in &node.rhs {
1207 let op = self.formula_operator(formula_operator);
1208 let rhs = self.factor(rhs);
1209 src = format!("{}{}{}", src, op, rhs);
1210 }
1211 if self.html {
1212 format!("<span class=\"mech-term\">{}</span>",src)
1213 } else {
1214 src
1215 }
1216 }
1217
1218 pub fn formula_operator(&mut self, node: &FormulaOperator) -> String {
1219 let f = match node {
1220 FormulaOperator::AddSub(op) => self.add_sub_op(op),
1221 FormulaOperator::MulDiv(op) => self.mul_div_op(op),
1222 FormulaOperator::Exponent(op) => self.exponent_op(op),
1223 FormulaOperator::Vec(op) => self.vec_op(op),
1224 FormulaOperator::Comparison(op) => self.comparison_op(op),
1225 FormulaOperator::Logic(op) => self.logic_op(op),
1226 };
1227 if self.html {
1228 format!("<span class=\"mech-formula-operator\">{}</span>",f)
1229 } else {
1230 format!(" {} ", f)
1231 }
1232 }
1233
1234 pub fn add_sub_op(&mut self, node: &AddSubOp) -> String {
1235 match node {
1236 AddSubOp::Add => "+".to_string(),
1237 AddSubOp::Sub => "-".to_string(),
1238 }
1239 }
1240
1241 pub fn mul_div_op(&mut self, node: &MulDivOp) -> String {
1242 match node {
1243 MulDivOp::Mul => "*".to_string(),
1244 MulDivOp::Div => "/".to_string(),
1245 }
1246 }
1247
1248 pub fn exponent_op(&mut self, node: &ExponentOp) -> String {
1249 match node {
1250 ExponentOp::Exp => "^".to_string(),
1251 }
1252 }
1253
1254 pub fn vec_op(&mut self, node: &VecOp) -> String {
1255 match node {
1256 VecOp::MatMul => "**".to_string(),
1257 VecOp::Solve => "\\".to_string(),
1258 VecOp::Cross => "×".to_string(),
1259 VecOp::Dot => "·".to_string(),
1260 }
1261 }
1262
1263 pub fn comparison_op(&mut self, node: &ComparisonOp) -> String {
1264 match node {
1265 ComparisonOp::Equal => "⩵".to_string(),
1266 ComparisonOp::NotEqual => "≠".to_string(),
1267 ComparisonOp::GreaterThan => ">".to_string(),
1268 ComparisonOp::GreaterThanEqual => "≥".to_string(),
1269 ComparisonOp::LessThan => "<".to_string(),
1270 ComparisonOp::LessThanEqual => "≤".to_string(),
1271 }
1272 }
1273
1274 pub fn logic_op(&mut self, node: &LogicOp) -> String {
1275 match node {
1276 LogicOp::And => "&".to_string(),
1277 LogicOp::Or => "|".to_string(),
1278 LogicOp::Xor => "xor".to_string(),
1279 LogicOp::Not => "¬".to_string(),
1280 }
1281 }
1282
1283 pub fn literal(&mut self, node: &Literal) -> String {
1284 let l = match node {
1285 Literal::Empty(token) => "_".to_string(),
1286 Literal::Boolean(token) => token.to_string(),
1287 Literal::Number(number) => self.number(number),
1288 Literal::String(mech_string) => self.string(mech_string),
1289 Literal::Atom(atom) => self.atom(atom),
1290 Literal::TypedLiteral((boxed_literal, kind_annotation)) => {
1291 let literal = self.literal(boxed_literal);
1292 let annotation = self.kind_annotation(kind_annotation);
1293 format!("{}{}", literal, annotation)
1294 }
1295 };
1296 if self.html {
1297 format!("<span class=\"mech-literal\">{}</span>",l)
1298 } else {
1299 l
1300 }
1301 }
1302
1303 pub fn atom(&mut self, node: &Atom) -> String {
1304 if self.html {
1305 format!("<span class=\"mech-atom\">{}</span>",node.name.to_string())
1306 } else {
1307 format!("`{}", node.name.to_string())
1308 }
1309 }
1310
1311 pub fn string(&mut self, node: &MechString) -> String {
1312 if self.html {
1313 format!("<span class=\"mech-string\">\"{}\"</span>", node.text.to_string())
1314 } else {
1315 format!("\"{}\"", node.text.to_string())
1316 }
1317 }
1318
1319 pub fn number(&mut self, node: &Number) -> String {
1320 let n = match node {
1321 Number::Real(real) => self.real_number(real),
1322 Number::Imaginary(complex) => self.complex_numer(complex),
1323 };
1324 if self.html {
1325 format!("<span class=\"mech-number\">{}</span>",n)
1326 } else {
1327 n
1328 }
1329 }
1330
1331 pub fn real_number(&mut self, node: &RealNumber) -> String {
1332 match node {
1333 RealNumber::Negated(real_number) => format!("-{}", self.real_number(real_number)),
1334 RealNumber::Integer(token) => token.to_string(),
1335 RealNumber::Float((whole, part)) => format!("{}.{}", whole.to_string(), part.to_string()),
1336 RealNumber::Decimal(token) => token.to_string(),
1337 RealNumber::Hexadecimal(token) => format!("0x{}", token.to_string()),
1338 RealNumber::Octal(token) => format!("0o{}", token.to_string()),
1339 RealNumber::Binary(token) => format!("0b{}", token.to_string()),
1340 RealNumber::Scientific(((whole, part), (sign, ewhole, epart))) => format!("{}.{}e{}{}.{}", whole.to_string(), part.to_string(), if *sign { "-" } else { "+" }, ewhole.to_string(), epart.to_string()),
1341 RealNumber::Rational((numerator, denominator)) => format!("{}/{}", numerator.to_string(), denominator.to_string()),
1342 }
1343 }
1344
1345 pub fn complex_numer(&mut self, node: &ComplexNumber) -> String {
1346 let real = if let Some(real) = &node.real {
1347 let num = self.real_number(&real);
1348 format!("{}+", num)
1349 } else {
1350 "".to_string()
1351 };
1352 let im = self.imaginary_number(&node.imaginary);
1353 format!("{}{}", real, im)
1354 }
1355
1356 pub fn imaginary_number(&mut self, node: &ImaginaryNumber) -> String {
1357 let real = self.real_number(&node.number);
1358 format!("{}i", real)
1359 }
1360
1361 pub fn humanize_html(input: String) -> String {
1362 let mut formatted = String::new();
1363 let mut indent_level: usize = 0;
1364 let mut i = 0;
1365 while i < input.len() {
1366 if let Some(start) = input[i..].find('<') {
1368 let tag_start = i + start;
1369 if let Some(end) = input[tag_start..].find('>') {
1370 let tag_end = tag_start + end + 1;
1371 let tag = &input[tag_start..tag_end];
1372 let content = &input[i..tag_start].trim();
1374 if !content.is_empty() {
1375 formatted.push('\n');
1376 formatted.push_str(&" ".repeat(indent_level));
1377 formatted.push_str(content);
1378 }
1379 if tag.starts_with("</") {
1381 indent_level = indent_level.saturating_sub(1);
1383 formatted.push('\n');
1384 formatted.push_str(&" ".repeat(indent_level));
1385 formatted.push_str(tag);
1386 } else if tag.ends_with("/>") {
1387 formatted.push('\n');
1389 formatted.push_str(&" ".repeat(indent_level));
1390 formatted.push_str(tag);
1391 } else {
1392 formatted.push('\n');
1394 formatted.push_str(&" ".repeat(indent_level));
1395 formatted.push_str(tag);
1396 indent_level += 1;
1397 }
1398 i = tag_end;
1400 continue;
1401 }
1402 }
1403 let content = &input[i..].trim();
1405 if !content.is_empty() {
1406 formatted.push('\n');
1407 formatted.push_str(&" ".repeat(indent_level));
1408 formatted.push_str(content);
1409 }
1410 break;
1411 }
1412 formatted
1413 }
1414
1415}