tamer: obj::xmle::xir::tree: Parse Text into Element
This simply adds support for Text nodes as a child of Element. This support unit tests for the upcoming change for xmle fragments.main
parent
f0f6f89745
commit
929a6c9815
|
@ -191,7 +191,7 @@
|
|||
//! For more information,
|
||||
//! see [`AttrParts`].
|
||||
|
||||
use super::{AttrValue, QName, Token};
|
||||
use super::{AttrValue, QName, Text, Token};
|
||||
use crate::span::Span;
|
||||
use std::{fmt::Display, mem::take};
|
||||
|
||||
|
@ -217,6 +217,12 @@ pub enum Tree {
|
|||
/// XML element.
|
||||
Element(Element),
|
||||
|
||||
/// Text node.
|
||||
///
|
||||
/// A text node cannot contain other [`Tree`] elements;
|
||||
/// sibling text nodes must exist within an [`Element`].
|
||||
Text(Text, Span),
|
||||
|
||||
/// This variant exists purely because `#[non_exhaustive]` has no effect
|
||||
/// within the crate.
|
||||
///
|
||||
|
@ -237,6 +243,16 @@ impl Into<Option<Element>> for Tree {
|
|||
}
|
||||
}
|
||||
|
||||
impl Into<Option<Text>> for Tree {
|
||||
#[inline]
|
||||
fn into(self) -> Option<Text> {
|
||||
match self {
|
||||
Self::Text(text, _) => Some(text),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Tree {
|
||||
/// Yield a reference to the inner value if it is an [`Element`],
|
||||
/// otherwise [`None`].
|
||||
|
@ -260,6 +276,23 @@ impl Tree {
|
|||
pub fn is_element(&self) -> bool {
|
||||
matches!(self, Self::Element(_))
|
||||
}
|
||||
|
||||
/// Yield a reference to the inner value if it is a [`Text`],
|
||||
/// otherwise [`None`].
|
||||
#[inline]
|
||||
pub fn as_text<'a>(&'a self) -> Option<&'a Text> {
|
||||
match self {
|
||||
Self::Text(text, _) => Some(text),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Yield the inner value if it is a [`Text`],
|
||||
/// otherwise [`None`].
|
||||
#[inline]
|
||||
pub fn into_text(self) -> Option<Text> {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Element node.
|
||||
|
@ -595,6 +628,20 @@ impl Stack {
|
|||
_ => todo! {},
|
||||
})
|
||||
}
|
||||
|
||||
/// Appends a text node as a child of an element.
|
||||
///
|
||||
/// This is valid only for a [`Stack::BuddingElement`].
|
||||
fn text(self, value: Text, span: Span) -> Result<Self> {
|
||||
Ok(match self {
|
||||
Self::BuddingElement(mut ele) => {
|
||||
ele.element.children.push(Tree::Text(value, span));
|
||||
|
||||
Self::BuddingElement(ele)
|
||||
}
|
||||
_ => todo! {},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// State while parsing a XIR token stream into a tree.
|
||||
|
@ -669,6 +716,7 @@ impl ParserState {
|
|||
stack.push_attr_value(value, span)
|
||||
}
|
||||
Token::AttrValue(value, span) => stack.close_attr(value, span),
|
||||
Token::Text(value, span) => stack.text(value, span),
|
||||
|
||||
todo => Err(ParseError::Todo(todo, stack)),
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ lazy_static! {
|
|||
}
|
||||
|
||||
mod tree {
|
||||
use crate::ir::xir::Text;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
|
@ -45,6 +47,20 @@ mod tree {
|
|||
let tree = Tree::Element(ele.clone());
|
||||
|
||||
assert_eq!(Some(&ele), tree.as_element());
|
||||
assert_eq!(None, tree.as_text());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn text_from_tree() {
|
||||
let text = Text::Escaped("foo".intern());
|
||||
let tree = Tree::Text(text, *S);
|
||||
|
||||
assert!(!tree.is_element());
|
||||
assert_eq!(None, tree.as_element());
|
||||
assert_eq!(None, tree.clone().into_element());
|
||||
|
||||
assert_eq!(Some(&text), tree.as_text());
|
||||
assert_eq!(Some(text), tree.into_text());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,6 +294,31 @@ fn element_with_child_with_attributes() {
|
|||
assert_eq!(sut.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn element_with_text() {
|
||||
let parent = "parent".unwrap_into();
|
||||
let text = Text::Escaped("inner text".into());
|
||||
|
||||
let toks = [
|
||||
Token::Open(parent, *S),
|
||||
Token::Text(text, *S2),
|
||||
Token::Close(Some(parent), *S3),
|
||||
]
|
||||
.into_iter();
|
||||
|
||||
let expected = Element {
|
||||
name: parent,
|
||||
attrs: AttrList::new(),
|
||||
children: vec![Tree::Text(text, *S2)],
|
||||
span: (*S, *S3),
|
||||
};
|
||||
|
||||
let mut sut = parser_from(toks);
|
||||
|
||||
assert_eq!(sut.next(), Some(Ok(Tree::Element(expected))));
|
||||
assert_eq!(sut.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parser_from_filters_incomplete() {
|
||||
let name = ("ns", "elem").unwrap_into();
|
||||
|
|
Loading…
Reference in New Issue