#![allow(missing_docs)]
use nom::*;
use crate::ligature::ligature;
use crate::parser::ast::Ast;
use crate::parser::error::{EmptyError, ErrorType};
use crate::parser::warning::{EmptyWarning, WarningType};
use crate::parser::{position, Span};
pub fn should_stop(c: char) -> bool {
c == '*' || c == '/' || c == '$' || c == '|'
}
pub fn error(span: Span, ty: ErrorType) -> Ast {
Ast::Error(EmptyError {
position: position(&span),
ty,
})
}
pub fn warning(span: Span, ty: WarningType) -> Ast {
Ast::Warning(EmptyWarning {
position: position(&span),
ty,
})
}
named!(pub parse_bold<Span, Ast>,
map!(
map_res!(preceded!(tag!("*"), take_until_and_consume!("*")), parse_group),
{ |(_,x)| Ast::Bold(Box::new(x)) }
)
);
named!(pub parse_italic<Span, Ast>,
map!(
map_res!(preceded!(tag!("/"), take_until_and_consume!("/")), parse_group),
{ |(_,x)| Ast::Italic(Box::new(x)) }
)
);
named!(pub parse_inline_math<Span, Ast>,
map!(preceded!(tag!("$"), take_until_and_consume!("$")), { |x: Span| Ast::InlineMath(x.fragment.0.into())} )
);
named!(pub parse_styled<Span, Ast>,
alt!(
parse_bold | parse_italic | parse_inline_math
)
);
named!(pub parse_comment<Span, Ast>,
map!(preceded!(tag!("||"), alt!(take_until_and_consume!("\n") | call!(rest))), { |_| Ast::Newline })
);
named!(pub parse_any<Span, Ast>,
alt!(
tag!("**") => { |x| warning(x, WarningType::ConsecutiveStars) }
| parse_comment
| parse_styled
| tag!("*") => { |x| error(x, ErrorType::UnmatchedStar) }
| tag!("/") => { |x| error(x, ErrorType::UnmatchedSlash) }
| tag!("$") => { |x| error(x, ErrorType::UnmatchedDollar) }
| tag!("|") => { |_| { Ast::Text(String::from("|")) } }
| take_till!(should_stop) => { |x: Span| { Ast::Text(ligature(x.fragment.0)) } }
)
);
named!(pub parse_group<Span, Ast>,
map!(many0!(parse_any), |x| Ast::Group(x))
);
named!(pub parse_paragraph<Span, Ast>,
map!(many0!(parse_any), |x| Ast::Paragraph(x))
);
named!(pub parse_line<Span, Ast>,
alt!(
map!(preceded!(take_until_and_consume!("\n"), take!(0)), |x| { error(x, ErrorType::MultipleLinesTitle) })
| map!(many0!(parse_any), |x| Ast::Group(x))
)
);
named!(pub parse_title_level<Span, usize>,
map!(
terminated!(preceded!(tag!("#"), take_while!(|x| x == '#')), take_while!(char::is_whitespace)),
|x| x.fragment.0.len() + 1
)
);
named!(pub parse_title<Span, Ast>,
do_parse!(
level: parse_title_level >>
content: parse_line >> ({
Ast::Title {
level: (level - 1) as u8,
content: Box::new(content)
}
})
)
);
named!(pub get_bloc<Span, Span>,
alt!(
terminated!(take_until_and_consume!("\n\n"), many0!(tag!("\n")))
| terminated!(take_until_and_consume!("\n"), eof!())
| call!(rest)
)
);
named!(pub parse_bloc_content<Span, Ast>,
alt!(
parse_title | parse_paragraph
)
);
named!(pub parse<Span, Ast>,
do_parse!(
title: many1!(map_res!(call!(get_bloc), parse_bloc_content)) >> ({
Ast::Group(title.into_iter().map(|x| x.1).collect())
})
)
);