1use super::dom::Attribute;
2use super::dom::Node;
3use super::namespaces::Namespace;
4use super::namespaces::NamespaceRegistry;
5use super::xml;
6use uexpr::tokenizer::Token;
7
8pub fn parse_tokens<'a>(
9 namespace_registry: &'a NamespaceRegistry,
10 default_namespace: &'a Namespace,
11 tokens: &[Token],
12) -> Node<'a> {
13 let mut nodes: Vec<Node> = Vec::new();
14 let mut i: usize = 0;
15
16 while i < tokens.len() {
17 match &tokens[i] {
18 Token::ElementStart => {
19 i += 1;
20 let element_result =
21 parse_element(namespace_registry, default_namespace, &tokens[i..]);
22 i += element_result.0;
23 nodes.push(element_result.1);
24 }
25 Token::ValueString(data) => {
26 nodes.push(Node::new_text(data.to_string()));
28 }
29 Token::ValueUInt(unsigned_integer) => {
30 nodes.push(Node::new_text(unsigned_integer.to_string()));
32 }
33 Token::ValueInt(integer) => {
34 nodes.push(Node::new_text(integer.to_string()));
36 }
37 Token::ValueFloat(float) => {
38 nodes.push(Node::new_text(float.to_string()));
40 }
41 Token::ValueBool(boolean) => {
42 if *boolean {
44 nodes.push(Node::new_text(String::from("T")));
45 } else {
46 nodes.push(Node::new_text(String::from("F")));
47 }
48 }
49 _ => {
50 panic!("Expected a starting token got a {:?} instead.", &tokens[i]);
51 }
52 }
53 i += 1;
54 }
55
56 if nodes.len() == 1 {
57 return nodes.pop().unwrap();
58 } else {
59 return Node::new_document_fragment(nodes);
60 }
61}
62
63fn parse_element<'a>(
64 namespace_registry: &'a NamespaceRegistry,
65 parent_namespace: &'a Namespace,
66 element_tokens: &[Token],
67) -> (usize, Node<'a>) {
68 if element_tokens.len() < 2 {
69 panic!(
70 "Minimum number of element_tokens is 2: [Token::ElementLocalName, Token::ElementEnd]"
71 );
72 }
73
74 let element_namespace: &Namespace;
75 let local_name: String;
76 let mut attributes: Vec<Attribute> = Vec::new();
77 let mut children: Vec<Node> = Vec::new();
78 let mut i: usize = 0;
79
80 match &element_tokens[i] {
81 Token::ElementPrefix(prefix) => {
82 match namespace_registry.get(&prefix) {
83 Some(namespace) => {
84 element_namespace = namespace;
85 }
86 None => panic!("Unknown namespace prefix in Token::ElementPrefix."),
87 }
88 i += 1;
89 }
90 _ => {
91 element_namespace = parent_namespace;
92 }
93 }
94
95 match &element_tokens[i] {
96 Token::ElementLocalName(name) => {
97 local_name = name.to_string();
98 i += 1;
99 }
100 _ => panic!("Expected a Token::ElementLocalName but did not get one!"),
101 }
102
103 while i < element_tokens.len() {
104 match &element_tokens[i] {
105 Token::ElementStart => {
106 i += 1;
107 let child_element_result =
108 parse_element(namespace_registry, element_namespace, &element_tokens[i..]);
109 i += child_element_result.0;
110 children.push(child_element_result.1);
111 }
112 Token::ElementEnd => {
113 return (
114 i,
115 Node::new_element(element_namespace, local_name, attributes, children),
116 );
117 }
118 Token::AttributeStart => {
119 i += 1;
120 let attribute_result =
121 parse_attribute(namespace_registry, element_namespace, &element_tokens[i..]);
122 i += attribute_result.0;
123 attributes.push(attribute_result.1);
124 }
125 Token::ValueString(data) => {
126 children.push(Node::new_text(data.to_string()));
128 }
129 Token::ValueUInt(unsigned_integer) => {
130 children.push(Node::new_text(unsigned_integer.to_string()));
132 }
133 Token::ValueInt(integer) => {
134 children.push(Node::new_text(integer.to_string()));
136 }
137 Token::ValueFloat(float) => {
138 children.push(Node::new_text(float.to_string()));
140 }
141 Token::ValueBool(boolean) => {
142 if *boolean {
144 children.push(Node::new_text(String::from("T")));
145 } else {
146 children.push(Node::new_text(String::from("F")));
147 }
148 }
149 _ => {
150 panic!(
151 "Expected a follow up to Token::ElementLocalName but got a {:?} instead.",
152 element_tokens[i]
153 );
154 }
155 }
156
157 i += 1;
158 }
159
160 panic!("Expected a Token::ElementEnd but ran out of tokens instead.");
161}
162
163fn parse_attribute<'a>(
164 namespace_registry: &'a NamespaceRegistry,
165 owner_element_namespace: &'a Namespace,
166 attribute_tokens: &[Token],
167) -> (usize, Attribute<'a>) {
168 if attribute_tokens.len() < 2 {
169 panic!("Minimum number of attribute_tokens is 2: [Token::AttributeLocalName, Token::AttributeEnd]");
170 }
171
172 let attribute_namespace: &Namespace;
173 let local_name: String;
174 let mut value: String = String::new();
175 let mut i: usize = 0;
176
177 match &attribute_tokens[i] {
178 Token::AttributePrefix(prefix) => {
179 match namespace_registry.get(&prefix) {
180 Some(namespace) => {
181 attribute_namespace = namespace;
182 }
183 None => panic!("Unknown namespace prefix in Token::AttributePrefix."),
184 }
185 i += 1;
186 }
187 _ => {
188 attribute_namespace = owner_element_namespace;
189 }
190 }
191
192 match &attribute_tokens[i] {
193 Token::AttributeLocalName(name) => {
194 local_name = name.to_string();
195 i += 1;
196 }
197 _ => panic!(
198 "Expected a Token::AttributeLocalName but got a {:?} instead.",
199 attribute_tokens[i]
200 ),
201 }
202
203 while i < attribute_tokens.len() {
204 match &attribute_tokens[i] {
205 Token::ValueString(data) => {
206 if value.len() > 0 {
207 value.push_str(" ");
208 }
209 value.push_str(&data);
210 }
211 Token::ValueUInt(unsigned_integer) => {
212 if value.len() > 0 {
213 value.push_str(" ");
214 }
215 value.push_str(&unsigned_integer.to_string());
216 }
217 Token::ValueInt(integer) => {
218 if value.len() > 0 {
219 value.push_str(" ");
220 }
221 value.push_str(&integer.to_string());
222 }
223 Token::ValueFloat(float) => {
224 if value.len() > 0 {
225 value.push_str(" ");
226 }
227 value.push_str(&float.to_string());
228 }
229 Token::ValueBool(boolean) => {
230 if value.len() > 0 {
231 value.push_str(" ");
232 }
233
234 if *boolean {
235 value.push_str("true");
236 } else {
237 value.push_str("false");
238 }
239 }
240 Token::AttributeEnd => match *attribute_namespace {
241 xml::NAMESPACE => return (i, xml::attribute_factory(local_name, value)),
242 _ => return (i, Attribute::new(attribute_namespace, local_name, value)),
243 },
244 _ => {
245 panic!(
246 "Expected a follow up to Token::AttributeLocalName but got a {:?} instead.",
247 attribute_tokens[i]
248 );
249 }
250 }
251
252 i += 1;
253 }
254
255 panic!("Expected a Token::AttributeEnd but ran out of tokens instead.");
256}
257
258#[cfg(test)]
259mod tests {
260 use super::*;
261
262 #[test]
263 fn parse_unprefixed_attribute() {
264 let nsr: NamespaceRegistry = NamespaceRegistry::new();
265 let ns: &Namespace = nsr.get("xhtml").unwrap();
266 let tokens: Vec<Token> = vec![
267 Token::AttributeLocalName("title".to_string()),
268 Token::ValueString("my value".to_string()),
269 Token::AttributeEnd,
270 ];
271 let expected = Attribute::new(ns, "title".to_string(), "my value".to_string());
272
273 assert_eq!(parse_attribute(&nsr, ns, &tokens[..]).1, expected);
274 }
275
276 #[test]
277 fn parse_prefixed_attribute_current_namespace() {
278 let nsr: NamespaceRegistry = NamespaceRegistry::new();
279 let ns: &Namespace = nsr.get("xhtml").unwrap();
280 let tokens: Vec<Token> = vec![
281 Token::AttributePrefix("xhtml".to_string()),
282 Token::AttributeLocalName("title".to_string()),
283 Token::ValueString("my value".to_string()),
284 Token::AttributeEnd,
285 ];
286 let expected = Attribute::new(ns, "title".to_string(), "my value".to_string());
287
288 assert_eq!(parse_attribute(&nsr, ns, &tokens[..]).1, expected);
289 }
290
291 #[test]
292 fn parse_prefixed_attribute_different_namespace() {
293 let nsr: NamespaceRegistry = NamespaceRegistry::new();
294 let ns: &Namespace = nsr.get("xhtml").unwrap();
295 let fns: &Namespace = nsr.get("svg").unwrap();
296 let tokens: Vec<Token> = vec![
297 Token::AttributePrefix("svg".to_string()),
298 Token::AttributeLocalName("cx".to_string()),
299 Token::ValueString("50".to_string()),
300 Token::AttributeEnd,
301 ];
302 let expected = Attribute::new(fns, "cx".to_string(), "50".to_string());
303
304 assert_eq!(parse_attribute(&nsr, ns, &tokens[..]).1, expected);
305 }
306
307 #[test]
308 fn parse_unprefixed_empty_element() {
309 let nsr: NamespaceRegistry = NamespaceRegistry::new();
310 let ns: &Namespace = nsr.get("xhtml").unwrap();
311 let tokens: Vec<Token> = vec![Token::ElementLocalName("br".to_string()), Token::ElementEnd];
312 let expected = Node::new_element(ns, "br".to_string(), vec![], vec![]);
313
314 assert_eq!(parse_element(&nsr, ns, &tokens[..]).1, expected);
315 }
316
317 #[test]
318 fn parse_prefixed_empty_element_current_namespace() {
319 let nsr: NamespaceRegistry = NamespaceRegistry::new();
320 let ns: &Namespace = nsr.get("xhtml").unwrap();
321 let tokens: Vec<Token> = vec![
322 Token::ElementPrefix("xhtml".to_string()),
323 Token::ElementLocalName("br".to_string()),
324 Token::ElementEnd,
325 ];
326 let expected = Node::new_element(ns, "br".to_string(), vec![], vec![]);
327
328 assert_eq!(parse_element(&nsr, ns, &tokens[..]).1, expected);
329 }
330
331 #[test]
332 fn parse_prefixed_empty_element_different_namespace() {
333 let nsr: NamespaceRegistry = NamespaceRegistry::new();
334 let ns: &Namespace = nsr.get("xhtml").unwrap();
335 let fns: &Namespace = nsr.get("svg").unwrap();
336 let tokens: Vec<Token> = vec![
337 Token::ElementPrefix("svg".to_string()),
338 Token::ElementLocalName("circle".to_string()),
339 Token::ElementEnd,
340 ];
341 let expected = Node::new_element(fns, "circle".to_string(), vec![], vec![]);
342
343 assert_eq!(parse_element(&nsr, ns, &tokens[..]).1, expected);
344 }
345
346 #[test]
347 fn parse_unprefixed_empty_element_local_attribute() {
348 let nsr: NamespaceRegistry = NamespaceRegistry::new();
349 let ns: &Namespace = nsr.get("xhtml").unwrap();
350 let tokens: Vec<Token> = vec![
351 Token::ElementLocalName("p".to_string()),
352 Token::AttributeStart,
353 Token::AttributeLocalName("title".to_string()),
354 Token::ValueString("My tooltip.".to_string()),
355 Token::AttributeEnd,
356 Token::ElementEnd,
357 ];
358 let attr = Attribute::new(ns, "title".to_string(), "My tooltip.".to_string());
359 let expected = Node::new_element(ns, "p".to_string(), vec![attr], vec![]);
360
361 assert_eq!(parse_element(&nsr, ns, &tokens[..]).1, expected);
362 }
363}