xml.rs (5167B)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | //! Assembles an expanded tree into valid XML.
use super::{MarkupDisplay, GenerationError, Formatter};
use crate::parse::parser::{self, ParseNode, ParseTree};
#[derive(Debug, Clone)]
pub struct XMLFormatter {
pub tree : ParseTree
}
impl XMLFormatter {
pub fn new(tree : ParseTree) -> Self {
Self { tree }
}
fn display_attribute(&self, attr : &parser::AttributeNode)
-> Result<String, GenerationError> {
if let Some(symbol) = (*attr.node).atomic() {
Ok(format!("{}=\"{}\"", attr.keyword, symbol.value))
} else {
Err(GenerationError::new("XML",
"Attribute can only contain symbols, numbers or strings",
&(*attr.node).site()))
}
}
}
pub const DEFAULT : &str =
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
impl MarkupDisplay for XMLFormatter {
fn document(&self) -> Result<String, GenerationError> {
let mut doc = String::new();
if self.tree.is_empty() {
return Ok(String::from(DEFAULT));
}
let stripped = parser::strip(&self.tree, true);
let current_node = stripped.get(0);
// Check if declaration exists.
let mut has_declaration = false;
if let Some(ParseNode::List(list)) = current_node.as_ref() {
if let Some(ParseNode::Symbol(declaration)) = list.get(0) {
if declaration.value.to_lowercase() == "?xml" {
has_declaration = true;
}
}
}
if !has_declaration {
doc += DEFAULT;
}
// Populate.
doc += &self.display()?;
doc += "<!-- Generated by SEAM, from symbolic-expressions \
into XML. -->\n";
Ok(doc)
}
fn generate(&self, f : Formatter)
-> Result<(), GenerationError> {
let mut tree_iter = self.tree.iter().peekable();
while let Some(node) = tree_iter.next() {
match node {
ParseNode::Symbol(node)
| ParseNode::Number(node) => {
// If the node ahead is so-called "symbolic", we can
// infere there was a space between them.
write!(f, "{}", node.value)?;
if let Some(peek) = tree_iter.peek() {
if peek.symbolic().is_some() {
write!(f, " ")?
}
}
},
ParseNode::String(node) => write!(f, "{}", node.value)?,
ParseNode::List(list) => {
let head = list.first();
let mut tag = "";
if let Some(head_node) = head {
if let ParseNode::Symbol(head_symbol) = head_node {
tag = &head_symbol.value;
write!(f, "<{}", tag)?;
} else {
// Error, tags can only have symbol values.
}
} else {
// Error, empty tags not supported.
}
let mut rest = &list[1..];
// Declarations behave differently.
let front = tag.as_bytes()[0] as char;
if front == '!' || front == '?' {
while !rest.is_empty() {
if let ParseNode::List(_list) = &rest[0] {
// TODO: Throw error.
} else {
if let Some(node) = rest[0].symbolic() {
write!(f, "{}", node.value)?;
} else if let ParseNode::Attribute(a) = &rest[0] {
write!(f, " {}", self.display_attribute(a)?)?;
} else {
// Error.
}
}
rest = &rest[1..];
}
if front == '?' {
write!(f, " ?>")?;
} else {
write!(f, ">")?;
}
continue;
}
while let Some(ParseNode::Attribute(attr)) = rest.first() {
write!(f, " {}", self.display_attribute(&attr)?)?;
rest = &rest[1..];
}
write!(f, ">")?;
let xml_fmt = XMLFormatter::new(rest.to_owned());
xml_fmt.generate(f)?;
write!(f, "</{}>", tag)?;
},
_ => return Err(GenerationError::new("XML",
"Unknonw node encountered.", &node.site()))
}
}
Ok(())
}
}
// TODO: Convert special characters to XML compatible ones.
// e.g.
// < => <
// > => >
// & => &
// " => "
// ! => !
// etc.
|