2022-11-12 12:45:17 -05:00
|
|
|
use crate::Span;
|
|
|
|
|
2022-11-28 14:12:49 -05:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
pub enum EventKind<C, E> {
|
|
|
|
Enter(C),
|
|
|
|
Element(E),
|
2022-11-28 18:33:43 -05:00
|
|
|
Exit(C),
|
2022-11-28 14:12:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
pub struct Event<C, A> {
|
|
|
|
pub kind: EventKind<C, A>,
|
|
|
|
pub span: Span,
|
|
|
|
}
|
|
|
|
|
2022-12-08 11:42:54 -05:00
|
|
|
pub struct Object<C, E> {
|
|
|
|
kind: ObjectKind<C, E>,
|
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum ObjectKind<C, E> {
|
|
|
|
Container(C),
|
|
|
|
Element(E),
|
|
|
|
}
|
|
|
|
|
2022-11-28 14:12:49 -05:00
|
|
|
#[derive(Debug, Clone)]
|
2022-11-12 12:45:17 -05:00
|
|
|
pub struct Tree<C, E> {
|
|
|
|
nodes: Vec<Node<C, E>>,
|
2022-11-28 14:19:22 -05:00
|
|
|
branch: Vec<NodeIndex>,
|
|
|
|
head: Option<NodeIndex>,
|
2022-11-12 12:45:17 -05:00
|
|
|
}
|
|
|
|
|
2022-12-08 11:42:54 -05:00
|
|
|
impl<C: Copy, E: Copy> Tree<C, E> {
|
2022-11-12 12:45:17 -05:00
|
|
|
fn new(nodes: Vec<Node<C, E>>) -> Self {
|
2022-12-08 11:42:54 -05:00
|
|
|
let head = nodes[NodeIndex::root().index()].next;
|
2022-11-28 14:19:22 -05:00
|
|
|
Self {
|
|
|
|
nodes,
|
|
|
|
branch: Vec::new(),
|
2022-12-08 11:42:54 -05:00
|
|
|
head,
|
2022-11-28 14:19:22 -05:00
|
|
|
}
|
2022-11-12 12:45:17 -05:00
|
|
|
}
|
2022-12-08 11:42:54 -05:00
|
|
|
|
|
|
|
pub fn neighbors(&self) -> impl Iterator<Item = Object<C, E>> + '_ {
|
|
|
|
let mut head = self.head;
|
|
|
|
std::iter::from_fn(move || {
|
|
|
|
head.take().map(|h| {
|
|
|
|
let n = &self.nodes[h.index()];
|
|
|
|
let kind = match &n.kind {
|
|
|
|
NodeKind::Root => unreachable!(),
|
|
|
|
NodeKind::Container(c, _) => ObjectKind::Container(*c),
|
|
|
|
NodeKind::Element(e) => ObjectKind::Element(*e),
|
|
|
|
};
|
|
|
|
let span = n.span;
|
|
|
|
head = n.next;
|
|
|
|
Object { kind, span }
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
2022-11-12 12:45:17 -05:00
|
|
|
}
|
|
|
|
|
2022-11-28 14:19:22 -05:00
|
|
|
impl<C: Copy, E: Copy> Iterator for Tree<C, E> {
|
2022-11-28 14:12:49 -05:00
|
|
|
type Item = Event<C, E>;
|
2022-11-12 12:45:17 -05:00
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
if let Some(head) = self.head {
|
|
|
|
let n = &self.nodes[head.index()];
|
2022-11-28 14:12:49 -05:00
|
|
|
let kind = match &n.kind {
|
2022-12-08 11:42:54 -05:00
|
|
|
NodeKind::Root => unreachable!(),
|
2022-11-12 12:45:17 -05:00
|
|
|
NodeKind::Container(c, child) => {
|
|
|
|
self.branch.push(head);
|
|
|
|
self.head = *child;
|
2022-11-28 14:12:49 -05:00
|
|
|
EventKind::Enter(*c)
|
2022-11-12 12:45:17 -05:00
|
|
|
}
|
|
|
|
NodeKind::Element(e) => {
|
|
|
|
self.head = n.next;
|
2022-11-28 14:12:49 -05:00
|
|
|
EventKind::Element(*e)
|
2022-11-12 12:45:17 -05:00
|
|
|
}
|
2022-11-28 14:12:49 -05:00
|
|
|
};
|
|
|
|
Some(Event { kind, span: n.span })
|
2022-11-12 12:45:17 -05:00
|
|
|
} else if let Some(block_ni) = self.branch.pop() {
|
2022-11-28 18:33:43 -05:00
|
|
|
let Node { next, kind, span } = &self.nodes[block_ni.index()];
|
|
|
|
let cont = if let NodeKind::Container(c, _) = kind {
|
|
|
|
c
|
|
|
|
} else {
|
|
|
|
panic!();
|
|
|
|
};
|
2022-11-12 12:45:17 -05:00
|
|
|
self.head = *next;
|
2022-11-28 14:12:49 -05:00
|
|
|
Some(Event {
|
2022-11-28 18:33:43 -05:00
|
|
|
kind: EventKind::Exit(*cont),
|
2022-11-28 14:12:49 -05:00
|
|
|
span: *span,
|
|
|
|
})
|
2022-11-12 12:45:17 -05:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
struct NodeIndex(std::num::NonZeroUsize);
|
|
|
|
|
|
|
|
impl NodeIndex {
|
|
|
|
fn new(i: usize) -> Self {
|
|
|
|
assert_ne!(i, usize::MAX);
|
|
|
|
Self((i + 1).try_into().unwrap())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn root() -> Self {
|
|
|
|
Self::new(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn index(self) -> usize {
|
|
|
|
usize::from(self.0) - 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
enum NodeKind<C, E> {
|
|
|
|
Root,
|
|
|
|
Container(C, Option<NodeIndex>),
|
|
|
|
Element(E),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
struct Node<C, E> {
|
|
|
|
span: Span,
|
|
|
|
kind: NodeKind<C, E>,
|
|
|
|
next: Option<NodeIndex>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct Builder<C, E> {
|
|
|
|
nodes: Vec<Node<C, E>>,
|
|
|
|
branch: Vec<NodeIndex>,
|
|
|
|
head: Option<NodeIndex>,
|
|
|
|
}
|
|
|
|
|
2022-11-28 14:12:49 -05:00
|
|
|
impl<C: Copy, E: Copy> Builder<C, E> {
|
2022-11-12 12:45:17 -05:00
|
|
|
pub(super) fn new() -> Self {
|
|
|
|
Builder {
|
|
|
|
nodes: vec![Node {
|
|
|
|
span: Span::default(),
|
|
|
|
kind: NodeKind::Root,
|
|
|
|
next: None,
|
|
|
|
}],
|
|
|
|
branch: vec![],
|
|
|
|
head: Some(NodeIndex::root()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn elem(&mut self, e: E, span: Span) {
|
|
|
|
self.add_node(Node {
|
|
|
|
span,
|
|
|
|
kind: NodeKind::Element(e),
|
|
|
|
next: None,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn enter(&mut self, c: C, span: Span) {
|
|
|
|
self.add_node(Node {
|
|
|
|
span,
|
|
|
|
kind: NodeKind::Container(c, None),
|
|
|
|
next: None,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn exit(&mut self) {
|
|
|
|
if self.head.is_some() {
|
|
|
|
self.head = None;
|
|
|
|
} else {
|
|
|
|
let last = self.branch.pop();
|
|
|
|
assert_ne!(last, None);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn finish(self) -> Tree<C, E> {
|
|
|
|
Tree::new(self.nodes)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn add_node(&mut self, node: Node<C, E>) {
|
|
|
|
let ni = NodeIndex::new(self.nodes.len());
|
|
|
|
self.nodes.push(node);
|
|
|
|
if let Some(head_ni) = &mut self.head {
|
|
|
|
let mut head = &mut self.nodes[head_ni.index()];
|
|
|
|
match &mut head.kind {
|
|
|
|
NodeKind::Root | NodeKind::Element(_) => {
|
|
|
|
// update next pointer of previous node
|
|
|
|
assert_eq!(head.next, None);
|
|
|
|
head.next = Some(ni);
|
|
|
|
}
|
|
|
|
NodeKind::Container(_, child) => {
|
|
|
|
self.branch.push(*head_ni);
|
|
|
|
// update child pointer of current container
|
|
|
|
assert_eq!(*child, None);
|
|
|
|
*child = Some(ni);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if let Some(block) = self.branch.pop() {
|
|
|
|
let mut block = &mut self.nodes[block.index()];
|
|
|
|
assert!(matches!(block.kind, NodeKind::Container(..)));
|
|
|
|
block.next = Some(ni);
|
|
|
|
} else {
|
|
|
|
panic!()
|
|
|
|
}
|
|
|
|
self.head = Some(ni);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-28 14:12:49 -05:00
|
|
|
impl<C: Copy + std::fmt::Display, E: Copy + std::fmt::Display> std::fmt::Display for Builder<C, E> {
|
2022-11-12 12:45:17 -05:00
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
self.clone().finish().fmt(f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-28 14:12:49 -05:00
|
|
|
impl<C: Copy + std::fmt::Display, E: Copy + std::fmt::Display> std::fmt::Display for Tree<C, E> {
|
2022-11-12 12:45:17 -05:00
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
const INDENT: &str = " ";
|
|
|
|
let mut level = 0;
|
2022-11-28 14:19:22 -05:00
|
|
|
for e in self.clone() {
|
2022-11-12 12:45:17 -05:00
|
|
|
let indent = INDENT.repeat(level);
|
2022-11-28 14:12:49 -05:00
|
|
|
match e.kind {
|
|
|
|
EventKind::Enter(container) => {
|
|
|
|
write!(f, "{}{}", indent, container)?;
|
2022-11-12 12:45:17 -05:00
|
|
|
level += 1;
|
|
|
|
}
|
2022-11-28 18:33:43 -05:00
|
|
|
EventKind::Exit(_) => {
|
2022-11-28 14:12:49 -05:00
|
|
|
level -= 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
EventKind::Element(element) => {
|
|
|
|
write!(f, "{}{}", indent, element)?;
|
2022-11-12 12:45:17 -05:00
|
|
|
}
|
|
|
|
}
|
2022-11-28 14:12:49 -05:00
|
|
|
writeln!(f, " ({}:{})", e.span.start(), e.span.end())?;
|
2022-11-12 12:45:17 -05:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use crate::Span;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn fmt_linear() {
|
|
|
|
let mut tree: super::Builder<u8, u8> = super::Builder::new();
|
|
|
|
tree.elem(1, Span::new(0, 1));
|
|
|
|
tree.elem(2, Span::new(1, 2));
|
|
|
|
tree.elem(3, Span::new(3, 4));
|
|
|
|
assert_eq!(
|
|
|
|
tree.to_string(),
|
|
|
|
concat!(
|
|
|
|
"1 (0:1)\n",
|
|
|
|
"2 (1:2)\n",
|
|
|
|
"3 (3:4)\n", //
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn fmt_container() {
|
|
|
|
let mut tree: super::Builder<u8, u16> = super::Builder::new();
|
|
|
|
tree.enter(1, Span::new(0, 1));
|
|
|
|
tree.elem(11, Span::new(0, 1));
|
|
|
|
tree.elem(12, Span::new(0, 1));
|
|
|
|
tree.exit();
|
|
|
|
tree.enter(2, Span::new(1, 5));
|
|
|
|
tree.enter(21, Span::new(2, 5));
|
|
|
|
tree.enter(211, Span::new(3, 4));
|
|
|
|
tree.elem(2111, Span::new(3, 4));
|
|
|
|
tree.exit();
|
|
|
|
tree.exit();
|
|
|
|
tree.enter(22, Span::new(4, 5));
|
|
|
|
tree.elem(221, Span::new(4, 5));
|
|
|
|
tree.exit();
|
|
|
|
tree.exit();
|
|
|
|
tree.enter(3, Span::new(5, 6));
|
|
|
|
tree.elem(31, Span::new(5, 6));
|
|
|
|
tree.exit();
|
|
|
|
assert_eq!(
|
|
|
|
tree.to_string(),
|
|
|
|
concat!(
|
|
|
|
"1 (0:1)\n",
|
|
|
|
" 11 (0:1)\n",
|
|
|
|
" 12 (0:1)\n",
|
|
|
|
"2 (1:5)\n",
|
|
|
|
" 21 (2:5)\n",
|
|
|
|
" 211 (3:4)\n",
|
|
|
|
" 2111 (3:4)\n",
|
|
|
|
" 22 (4:5)\n",
|
|
|
|
" 221 (4:5)\n",
|
|
|
|
"3 (5:6)\n",
|
|
|
|
" 31 (5:6)\n",
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|