imdom/
uexpr_token_parser.rs

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                // TODO convert to a <u:string>string</u:string>
27                nodes.push(Node::new_text(data.to_string()));
28            }
29            Token::ValueUInt(unsigned_integer) => {
30                // TODO convert to a <u:uint>uint</u:uint>
31                nodes.push(Node::new_text(unsigned_integer.to_string()));
32            }
33            Token::ValueInt(integer) => {
34                // TODO convert to a <u:int>int</u:int>
35                nodes.push(Node::new_text(integer.to_string()));
36            }
37            Token::ValueFloat(float) => {
38                // TODO convert to a <u:float>float</u:float>
39                nodes.push(Node::new_text(float.to_string()));
40            }
41            Token::ValueBool(boolean) => {
42                // TODO convert to a <u:true/> or <u:false/>
43                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                // TODO convert to a <u:string>string</u:string>
127                children.push(Node::new_text(data.to_string()));
128            }
129            Token::ValueUInt(unsigned_integer) => {
130                // TODO convert to a <u:uint>uint</u:uint>
131                children.push(Node::new_text(unsigned_integer.to_string()));
132            }
133            Token::ValueInt(integer) => {
134                // TODO convert to a <u:int>int</u:int>
135                children.push(Node::new_text(integer.to_string()));
136            }
137            Token::ValueFloat(float) => {
138                // TODO convert to a <u:float>float</u:float>
139                children.push(Node::new_text(float.to_string()));
140            }
141            Token::ValueBool(boolean) => {
142                // TODO convert to a <u:true/> or <u:false/>
143                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}