fixup! tree: add tree branch reference
This commit is contained in:
parent
a62eb3e1d8
commit
5e8c683050
3 changed files with 26 additions and 54 deletions
|
@ -12,7 +12,6 @@ use Leaf::*;
|
||||||
use ListType::*;
|
use ListType::*;
|
||||||
|
|
||||||
pub type Tree = tree::Tree<Node, Atom>;
|
pub type Tree = tree::Tree<Node, Atom>;
|
||||||
pub type Branch = tree::Branch<Node, Atom>;
|
|
||||||
pub type TreeBuilder = tree::Builder<Node, Atom>;
|
pub type TreeBuilder = tree::Builder<Node, Atom>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
@ -523,7 +522,7 @@ mod test {
|
||||||
macro_rules! test_parse {
|
macro_rules! test_parse {
|
||||||
($src:expr $(,$($event:expr),* $(,)?)?) => {
|
($src:expr $(,$($event:expr),* $(,)?)?) => {
|
||||||
let t = super::TreeParser::new($src).parse();
|
let t = super::TreeParser::new($src).parse();
|
||||||
let actual = t.root().map(|ev| (ev.kind, ev.span.of($src))).collect::<Vec<_>>();
|
let actual = t.map(|ev| (ev.kind, ev.span.of($src))).collect::<Vec<_>>();
|
||||||
let expected = &[$($($event),*,)?];
|
let expected = &[$($($event),*,)?];
|
||||||
assert_eq!(actual, expected, "\n\n{}\n\n", $src);
|
assert_eq!(actual, expected, "\n\n{}\n\n", $src);
|
||||||
};
|
};
|
||||||
|
|
14
src/lib.rs
14
src/lib.rs
|
@ -263,14 +263,11 @@ impl<'s> Container<'s> {
|
||||||
pub struct Parser<'s> {
|
pub struct Parser<'s> {
|
||||||
src: &'s str,
|
src: &'s str,
|
||||||
|
|
||||||
/// Block tree parsed at first, written once. This is never accessed directly, the data is read
|
|
||||||
/// via [`Branch`] cursors. This is here only to keep it alive during the `Parser`'s lifetime.
|
|
||||||
_tree_data: block::Tree,
|
|
||||||
/// Link definitions encountered during block parse, written once.
|
/// Link definitions encountered during block parse, written once.
|
||||||
link_definitions: std::collections::HashMap<&'s str, CowStr<'s>>,
|
link_definitions: std::collections::HashMap<&'s str, CowStr<'s>>,
|
||||||
|
|
||||||
/// Block tree cursor.
|
/// Block tree cursor.
|
||||||
tree: block::Branch,
|
tree: block::Tree,
|
||||||
/// Spans to the inlines in the block currently being parsed.
|
/// Spans to the inlines in the block currently being parsed.
|
||||||
inlines: span::InlineSpans<'s>,
|
inlines: span::InlineSpans<'s>,
|
||||||
/// Inline parser, recreated for each new inline.
|
/// Inline parser, recreated for each new inline.
|
||||||
|
@ -279,7 +276,7 @@ pub struct Parser<'s> {
|
||||||
/// Footnote references in the order they were encountered, without duplicates.
|
/// Footnote references in the order they were encountered, without duplicates.
|
||||||
footnote_references: Vec<&'s str>,
|
footnote_references: Vec<&'s str>,
|
||||||
/// Cache of footnotes to emit at the end.
|
/// Cache of footnotes to emit at the end.
|
||||||
footnotes: std::collections::HashMap<&'s str, block::Branch>,
|
footnotes: std::collections::HashMap<&'s str, block::Tree>,
|
||||||
/// Next or current footnote being parsed and emitted.
|
/// Next or current footnote being parsed and emitted.
|
||||||
footnote_index: usize,
|
footnote_index: usize,
|
||||||
/// Currently within a footnote.
|
/// Currently within a footnote.
|
||||||
|
@ -292,7 +289,7 @@ impl<'s> Parser<'s> {
|
||||||
let tree = block::parse(src);
|
let tree = block::parse(src);
|
||||||
|
|
||||||
let link_definitions = {
|
let link_definitions = {
|
||||||
let mut branch = tree.root();
|
let mut branch = tree.clone();
|
||||||
let mut defs = std::collections::HashMap::new();
|
let mut defs = std::collections::HashMap::new();
|
||||||
while let Some(e) = branch.next() {
|
while let Some(e) = branch.next() {
|
||||||
if let tree::EventKind::Enter(block::Node::Leaf(block::Leaf::LinkDefinition)) =
|
if let tree::EventKind::Enter(block::Node::Leaf(block::Leaf::LinkDefinition)) =
|
||||||
|
@ -310,11 +307,10 @@ impl<'s> Parser<'s> {
|
||||||
defs
|
defs
|
||||||
};
|
};
|
||||||
|
|
||||||
let branch = tree.root();
|
let branch = tree.clone();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
src,
|
src,
|
||||||
_tree_data: tree,
|
|
||||||
link_definitions,
|
link_definitions,
|
||||||
tree: branch,
|
tree: branch,
|
||||||
footnote_references: Vec::new(),
|
footnote_references: Vec::new(),
|
||||||
|
@ -523,7 +519,7 @@ impl<'s> Parser<'s> {
|
||||||
self.tree = self
|
self.tree = self
|
||||||
.footnotes
|
.footnotes
|
||||||
.remove(tag)
|
.remove(tag)
|
||||||
.unwrap_or_else(block::Branch::empty);
|
.unwrap_or_else(block::Tree::empty);
|
||||||
self.footnote_active = true;
|
self.footnote_active = true;
|
||||||
|
|
||||||
Some(Event::Start(
|
Some(Event::Start(
|
||||||
|
|
63
src/tree.rs
63
src/tree.rs
|
@ -14,45 +14,17 @@ pub struct Event<C, A> {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Tree<C, A>(Box<[Node<C, A>]>);
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Inlines<'t, C, A> {
|
pub struct Tree<C: 'static, A: 'static> {
|
||||||
iter: std::slice::Iter<'t, Node<C, A>>,
|
nodes: std::rc::Rc<[Node<C, A>]>,
|
||||||
}
|
|
||||||
|
|
||||||
impl<'t, C, A> Iterator for Inlines<'t, C, A> {
|
|
||||||
type Item = Span;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
self.iter.next().map(|n| n.span)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C, A> Tree<C, A> {
|
|
||||||
pub fn root(&self) -> Branch<C, A> {
|
|
||||||
let head = self.0[NodeIndex::root().index()].next;
|
|
||||||
// SAFETY: tree must outlive the branch
|
|
||||||
let nodes = unsafe { std::mem::transmute::<&[Node<C, A>], &'static [Node<C, A>]>(&self.0) };
|
|
||||||
Branch {
|
|
||||||
nodes,
|
|
||||||
branch: Vec::new(),
|
|
||||||
head,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Branch<C: 'static, A: 'static> {
|
|
||||||
nodes: &'static [Node<C, A>],
|
|
||||||
branch: Vec<NodeIndex>,
|
branch: Vec<NodeIndex>,
|
||||||
head: Option<NodeIndex>,
|
head: Option<NodeIndex>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, A> Branch<C, A> {
|
impl<C: Clone, A: Clone> Tree<C, A> {
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
Self {
|
Self {
|
||||||
nodes: &[],
|
nodes: vec![].into_boxed_slice().into(),
|
||||||
branch: Vec::new(),
|
branch: Vec::new(),
|
||||||
head: None,
|
head: None,
|
||||||
}
|
}
|
||||||
|
@ -78,7 +50,7 @@ impl<C, A> Branch<C, A> {
|
||||||
self.head = n.next;
|
self.head = n.next;
|
||||||
}
|
}
|
||||||
Self {
|
Self {
|
||||||
nodes: self.nodes,
|
nodes: self.nodes.clone(),
|
||||||
branch: Vec::new(),
|
branch: Vec::new(),
|
||||||
head,
|
head,
|
||||||
}
|
}
|
||||||
|
@ -99,7 +71,7 @@ impl<C, A> Branch<C, A> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Clone, A: Clone> Iterator for Branch<C, A> {
|
impl<C: Clone, A: Clone> Iterator for Tree<C, A> {
|
||||||
type Item = Event<C, A>;
|
type Item = Event<C, A>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
@ -223,7 +195,12 @@ impl<C: Clone, A: Clone> Builder<C, A> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn finish(self) -> Tree<C, A> {
|
pub(super) fn finish(self) -> Tree<C, A> {
|
||||||
Tree(self.nodes.into_boxed_slice())
|
let head = self.nodes[NodeIndex::root().index()].next;
|
||||||
|
Tree {
|
||||||
|
nodes: self.nodes.into_boxed_slice().into(),
|
||||||
|
branch: Vec::new(),
|
||||||
|
head,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_node(&mut self, node: Node<C, A>) {
|
fn add_node(&mut self, node: Node<C, A>) {
|
||||||
|
@ -259,11 +236,11 @@ impl<C: std::fmt::Debug + Clone + 'static, A: std::fmt::Debug + Clone + 'static>
|
||||||
for Builder<C, A>
|
for Builder<C, A>
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
self.clone().finish().root().fmt(f)
|
self.clone().finish().fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: std::fmt::Debug + Clone, A: std::fmt::Debug + Clone> std::fmt::Debug for Branch<C, A> {
|
impl<C: std::fmt::Debug + Clone, A: std::fmt::Debug + Clone> std::fmt::Debug for Tree<C, A> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
const INDENT: &str = " ";
|
const INDENT: &str = " ";
|
||||||
let mut level = 0;
|
let mut level = 0;
|
||||||
|
@ -348,11 +325,11 @@ mod test {
|
||||||
b.exit();
|
b.exit();
|
||||||
b.enter(3, sp);
|
b.enter(3, sp);
|
||||||
b.atom(31, sp);
|
b.atom(31, sp);
|
||||||
let tree = b.finish();
|
b.exit();
|
||||||
|
let mut tree = b.finish();
|
||||||
|
|
||||||
let mut root_branch = tree.root();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
(&mut root_branch).take(3).collect::<Vec<_>>(),
|
(&mut tree).take(3).collect::<Vec<_>>(),
|
||||||
&[
|
&[
|
||||||
Event {
|
Event {
|
||||||
kind: EventKind::Enter(1),
|
kind: EventKind::Enter(1),
|
||||||
|
@ -369,14 +346,14 @@ mod test {
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
root_branch.next(),
|
tree.next(),
|
||||||
Some(Event {
|
Some(Event {
|
||||||
kind: EventKind::Enter(2),
|
kind: EventKind::Enter(2),
|
||||||
span: sp
|
span: sp
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
root_branch.take_branch().collect::<Vec<_>>(),
|
tree.take_branch().collect::<Vec<_>>(),
|
||||||
&[
|
&[
|
||||||
Event {
|
Event {
|
||||||
kind: EventKind::Enter(21),
|
kind: EventKind::Enter(21),
|
||||||
|
@ -393,7 +370,7 @@ mod test {
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
root_branch.collect::<Vec<_>>(),
|
tree.collect::<Vec<_>>(),
|
||||||
&[
|
&[
|
||||||
Event {
|
Event {
|
||||||
kind: EventKind::Enter(3),
|
kind: EventKind::Enter(3),
|
||||||
|
|
Loading…
Reference in a new issue