jotdown/src/lib.rs

124 lines
3.1 KiB
Rust
Raw Normal View History

2022-11-12 12:45:17 -05:00
mod block;
2022-11-16 16:11:55 -05:00
mod inline;
2022-11-20 13:13:48 -05:00
mod lex;
2022-11-12 12:45:17 -05:00
mod span;
mod tree;
2022-11-20 13:13:48 -05:00
pub struct Block;
2022-11-12 12:45:17 -05:00
const EOF: char = '\0';
use span::Span;
2022-11-20 13:13:48 -05:00
pub struct Parser<'s> {
src: &'s str,
tree: block::Tree,
}
impl<'s> Parser<'s> {
2022-11-22 13:19:21 -05:00
#[must_use]
2022-11-20 13:13:48 -05:00
pub fn new(src: &'s str) -> Self {
Self {
src,
tree: block::parse(src),
}
}
2022-11-22 13:19:21 -05:00
#[must_use]
2022-11-20 13:13:48 -05:00
pub fn iter(&self) -> Iter {
Iter {
src: self.src,
2022-11-22 13:19:21 -05:00
tree: self.tree.iter(),
parser: None,
2022-11-20 13:13:48 -05:00
}
}
}
2022-11-22 13:19:21 -05:00
#[derive(Debug, PartialEq, Eq)]
pub enum Event {
Start(block::Block),
End,
Inline(inline::Event),
Blankline,
}
2022-11-20 13:13:48 -05:00
pub struct Iter<'s> {
src: &'s str,
2022-11-22 13:19:21 -05:00
tree: block::TreeIter<'s>,
parser: Option<inline::Parser<'s>>,
2022-11-20 13:13:48 -05:00
}
impl<'s> Iterator for Iter<'s> {
2022-11-22 13:19:21 -05:00
type Item = Event;
2022-11-20 13:13:48 -05:00
fn next(&mut self) -> Option<Self::Item> {
2022-11-22 13:19:21 -05:00
while let Some(parser) = &mut self.parser {
// inside leaf block, with inline content
if let Some(inline) = parser.next() {
return Some(Event::Inline(inline));
} else if let Some(ev) = self.tree.next() {
match ev {
tree::Event::Element(atom, sp) => {
assert_eq!(*atom, block::Atom::Inline);
parser.parse(sp.of(self.src));
}
tree::Event::Exit => {
self.parser = None;
return Some(Event::End);
2022-11-20 13:13:48 -05:00
}
2022-11-22 13:19:21 -05:00
tree::Event::Enter(..) => unreachable!(),
}
2022-11-20 13:13:48 -05:00
}
2022-11-22 13:19:21 -05:00
}
self.tree.next().map(|ev| match ev {
2022-11-20 13:13:48 -05:00
tree::Event::Element(atom, _sp) => {
2022-11-22 13:19:21 -05:00
assert_eq!(*atom, block::Atom::Blankline);
Event::Blankline
}
tree::Event::Enter(block @ block::Block::Container(..), ..) => {
Event::Start(block.clone())
2022-11-20 13:13:48 -05:00
}
2022-11-22 13:19:21 -05:00
tree::Event::Enter(block @ block::Block::Leaf(..), ..) => {
self.parser = Some(inline::Parser::new());
Event::Start(block.clone())
}
tree::Event::Exit => Event::End,
2022-11-20 13:13:48 -05:00
})
}
}
2022-11-22 13:19:21 -05:00
#[cfg(test)]
mod test {
use super::Event::*;
use crate::block::Block::*;
use crate::block::Container::*;
use crate::block::Leaf::*;
use crate::inline::Atom::*;
use crate::inline::Event::*;
2022-11-22 13:48:17 -05:00
macro_rules! test_parse {
($($st:ident,)? $src:expr $(,$($token:expr),* $(,)?)?) => {
#[allow(unused)]
let actual = super::Parser::new($src).iter().collect::<Vec<_>>();
let expected = &[$($($token),*,)?];
assert_eq!(actual, expected, "\n\n{}\n\n", $src);
};
}
2022-11-22 13:19:21 -05:00
#[test]
2022-11-22 13:48:17 -05:00
fn para() {
test_parse!("abc", Start(Leaf(Paragraph)), Inline(Atom(Str)), End);
test_parse!("abc def", Start(Leaf(Paragraph)), Inline(Atom(Str)), End);
test_parse!(
"this is a paragraph\n\nfollowed by another one",
Start(Leaf(Paragraph)),
Inline(Atom(Str)),
End,
Start(Leaf(Paragraph)),
Inline(Atom(Str)),
End,
2022-11-22 13:19:21 -05:00
);
}
}