Initial setup for the parser.
This commit is contained in:
134
src/parser/text.rs
Normal file
134
src/parser/text.rs
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
|
||||
hypothetical link:
|
||||
fn link = many_till(text_element, link_end)
|
||||
|
||||
but what if you start a bold?
|
||||
fn bold = many_till(text_element, bold_end) could eat the link_end
|
||||
|
||||
Do I pass along break-conditions? Passing link_end into bold's parser?
|
||||
|
||||
I'll try a very simple language first where asterisks always start/end bold and links are just between [ and ]. Paragraphs will have a blank line between them.
|
||||
|
||||
*/
|
||||
use nom::bytes::complete::tag;
|
||||
use nom::character::complete::alphanumeric1;
|
||||
use nom::character::complete::line_ending;
|
||||
use nom::character::complete::space1;
|
||||
use nom::combinator::map;
|
||||
use nom::combinator::recognize;
|
||||
use nom::error::VerboseError;
|
||||
use nom::multi::many_till;
|
||||
use nom::sequence::tuple;
|
||||
use nom::IResult;
|
||||
|
||||
pub type Res<T, U> = IResult<T, U, VerboseError<T>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TextElement<'a> {
|
||||
Span(Span<'a>),
|
||||
Space(Space<'a>),
|
||||
LineBreak(LineBreak<'a>),
|
||||
Symbol(Symbol<'a>),
|
||||
Bold(Bold<'a>),
|
||||
Link(Link<'a>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Span<'a> {
|
||||
contents: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Space<'a> {
|
||||
contents: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LineBreak<'a> {
|
||||
contents: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Symbol<'a> {
|
||||
contents: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BlankLine<'a> {
|
||||
contents: Vec<TextElement<'a>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Sequence<'a> {
|
||||
pub contents: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Bold<'a> {
|
||||
pub contents: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Link<'a> {
|
||||
contents: &'a str,
|
||||
}
|
||||
|
||||
pub fn line_break(input: &str) -> Res<&str, LineBreak> {
|
||||
map(line_ending, |s: &str| LineBreak { contents: s })(input)
|
||||
}
|
||||
|
||||
pub fn space(input: &str) -> Res<&str, Space> {
|
||||
map(space1, |s: &str| Space { contents: s })(input)
|
||||
}
|
||||
|
||||
pub fn span(input: &str) -> Res<&str, Span> {
|
||||
map(alphanumeric1, |s: &str| Span { contents: s })(input)
|
||||
}
|
||||
|
||||
pub fn symbol(symbol_tag: &'static str) -> impl for<'a> Fn(&'a str) -> Res<&'a str, Symbol<'a>> {
|
||||
move |i: &str| map(tag(symbol_tag), |s: &str| Symbol { contents: s })(i)
|
||||
}
|
||||
|
||||
/// A line containing only whitespace and then a line break
|
||||
///
|
||||
/// It is up to the caller to ensure this is called at the start of a line.
|
||||
fn blank_line(input: &str) -> Res<&str, BlankLine> {
|
||||
map(
|
||||
many_till(
|
||||
map(space, TextElement::Space),
|
||||
map(line_break, TextElement::LineBreak),
|
||||
),
|
||||
|(mut whitespace, end_of_line)| {
|
||||
whitespace.push(end_of_line);
|
||||
BlankLine {
|
||||
contents: whitespace,
|
||||
}
|
||||
},
|
||||
)(input)
|
||||
}
|
||||
|
||||
pub fn bold_start(input: &str) -> Res<&str, TextElement> {
|
||||
map(symbol("*"), TextElement::Symbol)(input)
|
||||
}
|
||||
|
||||
pub fn bold_end(input: &str) -> Res<&str, TextElement> {
|
||||
map(symbol("*"), TextElement::Symbol)(input)
|
||||
}
|
||||
|
||||
pub fn link_start(input: &str) -> Res<&str, TextElement> {
|
||||
map(symbol("["), TextElement::Symbol)(input)
|
||||
}
|
||||
|
||||
pub fn link_end(input: &str) -> Res<&str, TextElement> {
|
||||
map(symbol("]"), TextElement::Symbol)(input)
|
||||
}
|
||||
|
||||
pub fn paragraph(input: &str) -> Res<&str, (Vec<TextElement>, &str)> {
|
||||
todo!()
|
||||
// many_till(TextElementParser::new(paragraph_end), paragraph_end)(input)
|
||||
}
|
||||
|
||||
fn paragraph_end(input: &str) -> Res<&str, &str> {
|
||||
recognize(tuple((map(line_break, TextElement::LineBreak), blank_line)))(input)
|
||||
}
|
||||
Reference in New Issue
Block a user