use crate::{IRes, LocatedParseError, Span, shex_parser_error::ParseError as ShExParseError};
use nom::{
Err, Parser,
branch::alt,
bytes::complete::{is_not, tag, tag_no_case},
character::complete::multispace1,
combinator::value,
multi::many0,
sequence::{delimited, pair},
};
use std::fmt::Debug;
pub(crate) fn map_error<'a, T: 'a>(
mut parser: impl Parser<Span<'a>, Output = T, Error = LocatedParseError> + 'a,
mut error: impl FnMut() -> ShExParseError + 'a,
) -> impl FnMut(Span<'a>) -> IRes<'a, T> + 'a {
move |input| {
parser.parse(input).map_err(|e| match e {
Err::Incomplete(_) => e,
Err::Error(context) => {
let mut err = error().at(input);
err.append(context);
Err::Error(err)
},
Err::Failure(context) => {
let mut err = error().at(input);
err.append(context);
Err::Failure(err)
},
})
}
}
#[inline(always)]
pub(crate) fn traced<'a, T, P>(fun: &'static str, mut parser: P) -> impl FnMut(Span<'a>) -> IRes<'a, T>
where
T: Debug,
P: FnMut(Span<'a>) -> IRes<'a, T>,
{
move |input| {
tracing::trace!(target: "parser", "{fun}({input:?})");
let result = parser(input);
match &result {
Ok(_res) => {
},
Err(_e) => {
},
}
result
}
}
fn comment(input: Span) -> IRes<()> {
alt((
value((), pair(tag("#"), is_not("\n\r"))),
value((), tag("#")),
value((), multi_comment),
))
.parse(input)
}
fn multi_comment(i: Span) -> IRes<()> {
value((), delimited(tag("/*"), is_not("*/"), tag("*/"))).parse(i)
}
pub(crate) fn tws0(input: Span) -> IRes<()> {
value((), many0(alt((value((), multispace1), comment)))).parse(input)
}
pub(crate) fn token<'a>(token: &'a str) -> impl FnMut(Span<'a>) -> IRes<'a, Span<'a>> {
map_error(tag(token), || ShExParseError::ExpectedToken(token.to_string()))
}
pub(crate) fn token_tws<'a>(token: &'a str) -> impl FnMut(Span<'a>) -> IRes<'a, Span<'a>> {
map_error(delimited(tws0, tag(token), tws0), || {
ShExParseError::ExpectedToken(token.to_string())
})
}
pub(crate) fn token_tws_no_case<'a>(token: &'a str) -> impl FnMut(Span<'a>) -> IRes<'a, Span<'a>> {
map_error(delimited(tws0, tag_no_case(token), tws0), || {
ShExParseError::ExpectedToken(token.to_string())
})
}
pub(crate) fn tag_no_case_tws<'a>(token: &'a str) -> impl FnMut(Span<'a>) -> IRes<'a, Span<'a>> {
map_error(delimited(tws0, tag_no_case(token), tws0), || {
ShExParseError::ExpectedToken(token.to_string())
})
}