165 lines
3.4 KiB
Rust
165 lines
3.4 KiB
Rust
use std::{fmt::Display, ops::Range};
|
|
|
|
pub enum Text {
|
|
Span(Range<usize>),
|
|
Static(&'static str),
|
|
String(String),
|
|
}
|
|
impl Default for Text {
|
|
fn default() -> Self {
|
|
Self::Static("")
|
|
}
|
|
}
|
|
|
|
impl Text {
|
|
pub fn empty() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
match self {
|
|
Self::Span(s) => s.is_empty(),
|
|
Self::Static(s) => s.is_empty(),
|
|
Self::String(s) => s.is_empty(),
|
|
}
|
|
}
|
|
|
|
pub fn as_str<'a>(&'a self, text: &'a str) -> &'a str {
|
|
match self {
|
|
Self::Span(s) => &text[s.clone()],
|
|
Self::Static(s) => s,
|
|
Self::String(s) => s.as_str(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
|
pub struct NodeRef(usize);
|
|
#[derive(Default)]
|
|
pub struct NodeStorage {
|
|
tags: Vec<u16>,
|
|
parents: Vec<Option<NodeRef>>,
|
|
children: Vec<Vec<NodeRef>>,
|
|
siblings_prev: Vec<Option<NodeRef>>,
|
|
siblings_next: Vec<Option<NodeRef>>,
|
|
texts: Vec<Text>,
|
|
}
|
|
impl NodeStorage {
|
|
pub fn nodes(&self) -> impl Iterator<Item = NodeRef> {
|
|
(0..self.tags.len()).map(NodeRef)
|
|
}
|
|
|
|
pub fn new_node(&mut self, tag: u16) -> NodeRef {
|
|
let node = NodeRef(self.tags.len());
|
|
self.tags.push(tag);
|
|
self.parents.push(None);
|
|
self.children.push(vec![]);
|
|
self.siblings_prev.push(None);
|
|
self.siblings_next.push(None);
|
|
self.texts.push(Text::default());
|
|
|
|
node
|
|
}
|
|
|
|
pub fn tag(&self, node: NodeRef) -> u16 {
|
|
self.tags[node.0]
|
|
}
|
|
|
|
pub fn parent(&self, node: NodeRef) -> Option<NodeRef> {
|
|
self.parents[node.0]
|
|
}
|
|
|
|
pub fn set_parent(&mut self, child: NodeRef, parent: NodeRef) {
|
|
self.parents[child.0] = Some(parent);
|
|
}
|
|
|
|
pub fn children(&self, node: NodeRef) -> impl Iterator<Item = NodeRef> {
|
|
self.children[node.0].iter().copied()
|
|
}
|
|
|
|
pub fn append_child(&mut self, parent: NodeRef, child: NodeRef) {
|
|
self.set_parent(child, parent);
|
|
|
|
let children = &mut self.children[parent.0];
|
|
let child_index = children.len();
|
|
|
|
children.push(child);
|
|
|
|
if child_index > 0 {
|
|
let prev_index = child_index - 1;
|
|
let prev_sibling = children[prev_index];
|
|
self.set_sibling_next(prev_sibling, child);
|
|
self.set_sibling_prev(child, prev_sibling);
|
|
}
|
|
}
|
|
|
|
pub fn sibling_next(&mut self, node: NodeRef) -> Option<NodeRef> {
|
|
self.siblings_next[node.0]
|
|
}
|
|
|
|
pub fn set_sibling_next(&mut self, this: NodeRef, next: NodeRef) {
|
|
self.siblings_next[this.0] = Some(next);
|
|
}
|
|
|
|
pub fn sibling_prev(&mut self, node: NodeRef) -> Option<NodeRef> {
|
|
self.siblings_prev[node.0]
|
|
}
|
|
|
|
pub fn set_sibling_prev(&mut self, this: NodeRef, prev: NodeRef) {
|
|
self.siblings_prev[this.0] = Some(prev);
|
|
}
|
|
|
|
pub fn text(&self, node: NodeRef) -> &Text {
|
|
&self.texts[node.0]
|
|
}
|
|
|
|
pub fn set_text(&mut self, node: NodeRef, text: Text) {
|
|
self.texts[node.0] = text;
|
|
}
|
|
|
|
pub fn display_syntax<'a>(
|
|
&'a self,
|
|
text: &'a str,
|
|
node: NodeRef,
|
|
) -> impl Display + 'a {
|
|
struct DisplaySyntax<'a> {
|
|
nodes: &'a NodeStorage,
|
|
node: NodeRef,
|
|
text: &'a str,
|
|
}
|
|
|
|
impl Display for DisplaySyntax<'_> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
let s = match self.nodes.text(self.node) {
|
|
Text::Span(s) => &self.text[s.clone()],
|
|
Text::Static(s) => s,
|
|
Text::String(s) => s.as_str(),
|
|
};
|
|
|
|
write!(f, "{s}")?;
|
|
for child in self.nodes.children(self.node) {
|
|
write!(
|
|
f,
|
|
"{}",
|
|
self.nodes.display_syntax(self.text, child)
|
|
)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
DisplaySyntax {
|
|
nodes: self,
|
|
node,
|
|
text,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl NodeStorage {
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
}
|