subscript_compiler/frontend/pass/
to_html.rs1use std::iter::FromIterator;
3use std::collections::{HashSet, HashMap};
4use std::rc::Rc;
5use std::borrow::Cow;
6use crate::frontend::data::*;
7use crate::frontend::ast::*;
8use crate::frontend::pass;
9
10use crate::codegen::html;
11
12pub(crate) fn node_to_html<'a>(node: Node<'a>) -> html::Node<'a> {
15 fn enclosure<'a>(
16 start: &'a str,
17 children: Vec<Node<'a>>,
18 end: &'a str,
19 ) -> html::Node<'a> {
20 html::Node::Fragment(
21 vec![
22 vec![html::Node::new_text(start)],
23 children.into_iter().map(node_to_html).collect::<Vec<_>>(),
24 vec![html::Node::new_text(end)],
25 ].concat()
26 )
27 }
28 fn enclosure_cow<'a>(
29 start: Atom<'a>,
30 children: Vec<Node<'a>>,
31 end: Option<Atom<'a>>,
32 ) -> html::Node<'a> {
33 let end = match end {
34 Some(x) => x,
35 None => Cow::Owned(String::new()),
36 };
37 html::Node::Fragment(
38 vec![
39 vec![html::Node::Text(Text(start))],
40 children.into_iter().map(node_to_html).collect::<Vec<_>>(),
41 vec![html::Node::Text(Text(end))],
42 ].concat()
43 )
44 }
45 fn map_children<'a>(children: Vec<Node<'a>>) -> Vec<html::Node<'a>> {
46 children.into_iter().map(node_to_html).collect::<Vec<_>>()
47 }
48 fn to_html_attributes<'a>(parameters: Vec<Node<'a>>) -> HashMap<Text<'a>, Text<'a>> {
49 parameters
50 .into_iter()
51 .filter_map(|node| -> Option<Text<'a>> {
52 match node {
53 Node::String(Ann{data: txt, ..}) if !txt.trim().is_empty() => {
54 Some(Text(txt))
55 }
56 _ => None
57 }
58 })
59 .map(|x| -> (Text<'a>, Text<'a>) {
60 if let Some((l, r)) = x.0.split_once("=") {
61 (Text(Cow::Owned(l.to_owned())), Text(Cow::Owned(r.to_owned())))
62 } else {
63 (x, Text(Cow::Borrowed("")))
64 }
65 })
66 .collect::<HashMap<_, _>>()
67 }
68 match node {
69 Node::Tag(node) => {
70 html::Node::Element(html::Element {
71 name: Text(node.name.data),
72 attributes: node.parameters
73 .map(to_html_attributes)
74 .unwrap_or_default(),
75 children: map_children(node.children),
76 })
77 },
78 Node::Enclosure(Ann{data: Enclosure {
79 kind: EnclosureKind::CurlyBrace,
80 children
81 }, ..}) => {
82 enclosure(
83 "{",
84 children,
85 "}"
86 )
87 },
88 Node::Enclosure(Ann{data: Enclosure {
89 kind: EnclosureKind::Parens,
90 children
91 }, ..}) => {
92 enclosure(
93 "(",
94 children,
95 ")"
96 )
97 },
98 Node::Enclosure(Ann{data: Enclosure {
99 kind: EnclosureKind::Fragment,
100 children
101 }, ..}) => {
102 html::Node::Fragment(map_children(children))
103 },
104 Node::Enclosure(Ann{data: Enclosure {
105 kind: EnclosureKind::SquareParen,
106 children
107 }, ..}) => {
108 enclosure(
109 "[",
110 children,
111 "]"
112 )
113 },
114 Node::Enclosure(Ann{data: Enclosure {
115 kind: EnclosureKind::Error{open, close},
116 children
117 }, ..}) => {
118 enclosure_cow(
119 open,
120 children,
121 close
122 )
123 },
124 Node::Ident(Ann{data, ..}) => {
125 html::Node::Text(Text::new("\\").append(Text(data)))
126 },
127 Node::String(Ann{data, ..}) => {
128 html::Node::Text(Text(data))
129 },
130 Node::InvalidToken(Ann{data, ..}) => {
131 html::Node::Text(Text(data))
132 }
133 }
134}
135
136