block: specify link def label in event

instead of using span
This commit is contained in:
Noah Hellman 2023-04-29 18:42:31 +02:00
parent bc4dd794bc
commit e90594f2b7
3 changed files with 56 additions and 53 deletions

View file

@ -12,13 +12,13 @@ use Container::*;
use Leaf::*; use Leaf::*;
use ListType::*; use ListType::*;
pub type Tree = tree::Tree<Node, Atom>; pub type Tree<'s> = tree::Tree<Node<'s>, Atom>;
pub type TreeBuilder = tree::Builder<Node, Atom>; pub type TreeBuilder<'s> = tree::Builder<Node<'s>, Atom>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Node { pub enum Node<'s> {
Container(Container), Container(Container),
Leaf(Leaf), Leaf(Leaf<'s>),
} }
#[must_use] #[must_use]
@ -27,12 +27,12 @@ pub fn parse(src: &str) -> Tree {
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Block { enum Block<'s> {
/// An atomic block, containing no children elements. /// An atomic block, containing no children elements.
Atom(Atom), Atom(Atom),
/// A leaf block, containing only inline elements. /// A leaf block, containing only inline elements.
Leaf(Leaf), Leaf(Leaf<'s>),
/// A container block, containing children blocks. /// A container block, containing children blocks.
Container(Container), Container(Container),
@ -51,7 +51,7 @@ pub enum Atom {
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Leaf { pub enum Leaf<'s> {
/// Span is empty, before first character of paragraph. /// Span is empty, before first character of paragraph.
/// Each inline is a line. /// Each inline is a line.
Paragraph, Paragraph,
@ -72,7 +72,7 @@ pub enum Leaf {
/// Span is the link tag. /// Span is the link tag.
/// Inlines are lines of the URL. /// Inlines are lines of the URL.
LinkDefinition, LinkDefinition { label: &'s str },
/// Span is language specifier. /// Span is language specifier.
/// Each inline is a line. /// Each inline is a line.
@ -135,7 +135,7 @@ struct OpenList {
/// Parser for block-level tree structure of entire document. /// Parser for block-level tree structure of entire document.
struct TreeParser<'s> { struct TreeParser<'s> {
src: &'s str, src: &'s str,
tree: TreeBuilder, tree: TreeBuilder<'s>,
/// The previous block element was a blank line. /// The previous block element was a blank line.
prev_blankline: bool, prev_blankline: bool,
@ -163,7 +163,7 @@ impl<'s> TreeParser<'s> {
} }
#[must_use] #[must_use]
pub fn parse(mut self) -> Tree { pub fn parse(mut self) -> Tree<'s> {
let mut lines = lines(self.src).collect::<Vec<_>>(); let mut lines = lines(self.src).collect::<Vec<_>>();
let mut line_pos = 0; let mut line_pos = 0;
while line_pos < lines.len() { while line_pos < lines.len() {
@ -246,7 +246,33 @@ impl<'s> TreeParser<'s> {
self.prev_blankline = false; self.prev_blankline = false;
} }
match kind.block(top_level) { let block = match kind {
Kind::Atom(a) => Block::Atom(a),
Kind::Paragraph => Block::Leaf(Paragraph),
Kind::Heading { level } => Block::Leaf(Heading {
level: level.try_into().unwrap(),
has_section: top_level,
}),
Kind::Fenced {
kind: FenceKind::CodeBlock(..),
..
} => Block::Leaf(CodeBlock),
Kind::Fenced {
kind: FenceKind::Div,
..
} => Block::Container(Div),
Kind::Definition {
footnote: false, ..
} => Block::Leaf(LinkDefinition {
label: span.of(self.src),
}),
Kind::Definition { footnote: true, .. } => Block::Container(Footnote),
Kind::Blockquote => Block::Container(Blockquote),
Kind::ListItem { ty, .. } => Block::Container(ListItem(ty)),
Kind::Table { .. } => Block::Container(Table),
};
match block {
Block::Atom(a) => self.tree.atom(a, span), Block::Atom(a) => self.tree.atom(a, span),
Block::Leaf(l) => self.parse_leaf(l, &kind, span, lines), Block::Leaf(l) => self.parse_leaf(l, &kind, span, lines),
Block::Container(Table) => self.parse_table(lines, span), Block::Container(Table) => self.parse_table(lines, span),
@ -259,7 +285,7 @@ impl<'s> TreeParser<'s> {
} }
} }
fn parse_leaf(&mut self, leaf: Leaf, k: &Kind, span: Span, lines: &mut [Span]) { fn parse_leaf(&mut self, leaf: Leaf<'s>, k: &Kind, span: Span, lines: &mut [Span]) {
if let Kind::Fenced { indent, .. } = k { if let Kind::Fenced { indent, .. } = k {
for line in lines.iter_mut() { for line in lines.iter_mut() {
let indent_line = line let indent_line = line
@ -564,7 +590,7 @@ impl<'s> TreeParser<'s> {
} }
} }
impl<'t> tree::Element<'t, Node, Atom> { impl<'t, 's> tree::Element<'t, Node<'s>, Atom> {
fn list_mut(&mut self) -> Option<&mut ListKind> { fn list_mut(&mut self) -> Option<&mut ListKind> {
if let tree::Element::Container(Node::Container(Container::List(l))) = self { if let tree::Element::Container(Node::Container(Container::List(l))) = self {
Some(l) Some(l)
@ -936,35 +962,9 @@ impl Kind {
} }
} }
} }
fn block(&self, top_level: bool) -> Block {
match self {
Self::Atom(a) => Block::Atom(*a),
Self::Paragraph => Block::Leaf(Paragraph),
Self::Heading { level } => Block::Leaf(Heading {
level: (*level).try_into().unwrap(),
has_section: top_level,
}),
Self::Fenced {
kind: FenceKind::CodeBlock(..),
..
} => Block::Leaf(CodeBlock),
Self::Fenced {
kind: FenceKind::Div,
..
} => Block::Container(Div),
Self::Definition {
footnote: false, ..
} => Block::Leaf(LinkDefinition),
Self::Definition { footnote: true, .. } => Block::Container(Footnote),
Self::Blockquote => Block::Container(Blockquote),
Self::ListItem { ty, .. } => Block::Container(ListItem(*ty)),
Self::Table { .. } => Block::Container(Table),
}
}
} }
impl std::fmt::Display for Block { impl<'s> std::fmt::Display for Block<'s> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Block::Atom(a) => std::fmt::Debug::fmt(a, f), Block::Atom(a) => std::fmt::Debug::fmt(a, f),
@ -1501,9 +1501,9 @@ mod test {
fn parse_link_definition() { fn parse_link_definition() {
test_parse!( test_parse!(
"[tag]: url\n", "[tag]: url\n",
(Enter(Leaf(LinkDefinition)), "tag"), (Enter(Leaf(LinkDefinition { label: "tag" })), "tag"),
(Inline, "url"), (Inline, "url"),
(Exit(Leaf(LinkDefinition)), "tag"), (Exit(Leaf(LinkDefinition { label: "tag" })), "tag"),
); );
} }

View file

@ -555,7 +555,7 @@ pub struct Parser<'s> {
src: &'s str, src: &'s str,
/// Block tree parsed at first. /// Block tree parsed at first.
tree: block::Tree, tree: block::Tree<'s>,
/// Contents obtained by the prepass. /// Contents obtained by the prepass.
pre_pass: PrePass<'s>, pre_pass: PrePass<'s>,
@ -598,7 +598,11 @@ struct PrePass<'s> {
impl<'s> PrePass<'s> { impl<'s> PrePass<'s> {
#[must_use] #[must_use]
fn new(src: &'s str, mut tree: block::Tree, inline_parser: &mut inline::Parser<'s>) -> Self { fn new(
src: &'s str,
mut tree: block::Tree<'s>,
inline_parser: &mut inline::Parser<'s>,
) -> Self {
let mut link_definitions = Map::new(); let mut link_definitions = Map::new();
let mut headings: Vec<Heading> = Vec::new(); let mut headings: Vec<Heading> = Vec::new();
let mut used_ids: Set<&str> = Set::new(); let mut used_ids: Set<&str> = Set::new();
@ -606,10 +610,11 @@ impl<'s> PrePass<'s> {
let mut attr_prev: Option<Span> = None; let mut attr_prev: Option<Span> = None;
while let Some(e) = tree.next() { while let Some(e) = tree.next() {
match e.kind { match e.kind {
tree::EventKind::Enter(block::Node::Leaf(block::Leaf::LinkDefinition)) => { tree::EventKind::Enter(block::Node::Leaf(block::Leaf::LinkDefinition {
label,
})) => {
// All link definition tags have to be obtained initially, as references can // All link definition tags have to be obtained initially, as references can
// appear before the definition. // appear before the definition.
let tag = e.span.of(src);
let attrs = let attrs =
attr_prev.map_or_else(Attributes::new, |sp| attr::parse(sp.of(src))); attr_prev.map_or_else(Attributes::new, |sp| attr::parse(sp.of(src)));
let url = match tree.count_children() { let url = match tree.count_children() {
@ -617,7 +622,7 @@ impl<'s> PrePass<'s> {
1 => tree.take_inlines().next().unwrap().of(src).trim().into(), 1 => tree.take_inlines().next().unwrap().of(src).trim().into(),
_ => tree.take_inlines().map(|sp| sp.of(src).trim()).collect(), _ => tree.take_inlines().map(|sp| sp.of(src).trim()).collect(),
}; };
link_definitions.insert(tag, (url, attrs)); link_definitions.insert(label, (url, attrs));
} }
tree::EventKind::Enter(block::Node::Leaf(block::Leaf::Heading { .. })) => { tree::EventKind::Enter(block::Node::Leaf(block::Leaf::Heading { .. })) => {
// All headings ids have to be obtained initially, as references can appear // All headings ids have to be obtained initially, as references can appear
@ -905,8 +910,8 @@ impl<'s> Parser<'s> {
head: self.table_head_row, head: self.table_head_row,
}, },
block::Leaf::Caption => Container::Caption, block::Leaf::Caption => Container::Caption,
block::Leaf::LinkDefinition => { block::Leaf::LinkDefinition { label } => {
Container::LinkDefinition { label: content } Container::LinkDefinition { label }
} }
} }
} }

View file

@ -29,7 +29,7 @@ pub struct Event<C, A> {
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Tree<C: 'static, A: 'static> { pub struct Tree<C, A> {
nodes: std::rc::Rc<[InternalNode<C, A>]>, nodes: std::rc::Rc<[InternalNode<C, A>]>,
branch: Vec<NodeIndex>, branch: Vec<NodeIndex>,
head: Option<NodeIndex>, head: Option<NodeIndex>,
@ -349,9 +349,7 @@ impl<C, A> Builder<C, A> {
} }
} }
impl<C: std::fmt::Debug + Clone + 'static, A: std::fmt::Debug + Clone + 'static> std::fmt::Debug impl<C: std::fmt::Debug + Clone, A: std::fmt::Debug + Clone> std::fmt::Debug 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().fmt(f) self.clone().finish().fmt(f)
} }