1use crate::{shex_parser_error::ParseError as ShExParseError, IRes, Span};
2use colored::*;
3use nom::{
4 branch::alt,
5 bytes::complete::{is_not, tag, tag_no_case},
6 character::complete::multispace1,
7 combinator::value,
8 multi::many0,
9 sequence::{delimited, pair},
10 Err,
11};
12use std::fmt::Debug;
13
14pub(crate) fn map_error<'a, T: 'a>(
24 mut parser: impl FnMut(Span<'a>) -> IRes<'a, T> + 'a,
25 mut error: impl FnMut() -> ShExParseError + 'a,
26) -> impl FnMut(Span<'a>) -> IRes<'a, T> + 'a {
27 move |input| {
28 parser(input).map_err(|e| match e {
29 Err::Incomplete(_) => e,
30 Err::Error(context) => {
31 let mut err = error().at(input);
32 err.append(context);
33 Err::Error(err)
34 }
35 Err::Failure(context) => {
36 let mut err = error().at(input);
37 err.append(context);
38 Err::Failure(err)
39 }
40 })
41 }
42}
43
44#[inline(always)]
47pub(crate) fn traced<'a, T, P>(
48 fun: &'static str,
49 mut parser: P,
50) -> impl FnMut(Span<'a>) -> IRes<'a, T>
51where
52 T: Debug,
53 P: FnMut(Span<'a>) -> IRes<'a, T>,
54{
55 move |input| {
56 tracing::trace!(target: "parser", "{fun}({input:?})");
57 let result = parser(input);
58 match &result {
59 Ok(res) => {
60 tracing::trace!(target: "parser", "{}", format!("{fun}({input:?}) -> {res:?}").green());
61 }
62 Err(e) => {
63 tracing::trace!(target: "parser", "{}", format!("{fun}({input:?}) -> {e:?}").red());
64 }
65 }
66 result
67 }
68}
69
70fn comment(input: Span) -> IRes<()> {
73 alt((
74 value((), pair(tag("#"), is_not("\n\r"))),
75 value((), tag("#")),
78 value((), multi_comment),
79 ))(input)
80}
81
82fn multi_comment(i: Span) -> IRes<()> {
83 value((), delimited(tag("/*"), is_not("*/"), tag("*/")))(i)
84}
85
86pub(crate) fn tws0(input: Span) -> IRes<()> {
89 value((), many0(alt((value((), multispace1), comment))))(input)
90}
91
92pub(crate) fn token<'a>(token: &'a str) -> impl FnMut(Span<'a>) -> IRes<'a, Span<'a>> {
102 map_error(tag(token), || {
103 ShExParseError::ExpectedToken(token.to_string())
104 })
105}
106
107pub(crate) fn token_tws<'a>(token: &'a str) -> impl FnMut(Span<'a>) -> IRes<'a, Span<'a>> {
110 map_error(delimited(tws0, tag(token), tws0), || {
111 ShExParseError::ExpectedToken(token.to_string())
112 })
113}
114
115pub(crate) fn tag_no_case_tws<'a>(token: &'a str) -> impl FnMut(Span<'a>) -> IRes<'a, Span<'a>> {
118 map_error(delimited(tws0, tag_no_case(token), tws0), || {
119 ShExParseError::ExpectedToken(token.to_string())
120 })
121}