markdown_ppp/parser/
util.rs

1use crate::ast::{Block, Inline};
2use nom::{
3    branch::alt,
4    character::complete::{anychar, line_ending, not_line_ending, space0},
5    combinator::{eof, fail, not, recognize, value},
6    multi::{many0, many1},
7    sequence::{preceded, terminated},
8    IResult, Parser,
9};
10
11pub(crate) fn eof_or_eol(input: &str) -> IResult<&str, &str> {
12    alt((line_ending, eof)).parse(input)
13}
14
15pub(crate) fn many_empty_lines0(input: &str) -> IResult<&str, Vec<&str>> {
16    many0(preceded(space0, eof_or_eol)).parse(input)
17}
18
19pub(crate) fn not_eof_or_eol1(input: &str) -> IResult<&str, &str> {
20    recognize(many1(preceded(not(eof_or_eol), anychar))).parse(input)
21}
22
23pub(crate) fn not_eof_or_eol0(input: &str) -> IResult<&str, &str> {
24    alt((not_line_ending, eof)).parse(input)
25}
26
27pub(crate) fn line_terminated<'a, O, P>(
28    inner: P,
29) -> impl Parser<&'a str, Output = O, Error = nom::error::Error<&'a str>>
30where
31    P: Parser<&'a str, Output = O, Error = nom::error::Error<&'a str>>,
32{
33    terminated(inner, eof_or_eol)
34}
35
36// pub(crate) fn logged<'a, O, P>(
37//     message: &'static str,
38//     mut inner: P,
39// ) -> impl Parser<&'a str, Output = O, Error = nom::error::Error<&'a str>>
40// where
41//     P: Parser<&'a str, Output = O, Error = nom::error::Error<&'a str>>,
42//     O: std::fmt::Debug,
43// {
44//     move |input: &'a str| {
45//         println!("Logged: {message}: {:?}", input);
46//         let r = inner.parse(input);
47//         println!("Logged out: {message}: {:?}", r);
48//         r
49//     }
50// }
51
52pub(crate) fn conditional<'a, O, P>(
53    behavior: crate::parser::config::ElementBehavior<O>,
54    default: Vec<O>,
55    mut inner: P,
56) -> impl Parser<&'a str, Output = Vec<O>, Error = nom::error::Error<&'a str>>
57where
58    P: Parser<&'a str, Output = O, Error = nom::error::Error<&'a str>>,
59    O: Clone,
60{
61    move |input: &'a str| {
62        let inner1 = |s: &'a str| inner.parse(s);
63        match &behavior {
64            crate::parser::config::ElementBehavior::Ignore => fail().map(|v| vec![v]).parse(input),
65            crate::parser::config::ElementBehavior::Parse => inner1.map(|v| vec![v]).parse(input),
66            crate::parser::config::ElementBehavior::Skip => {
67                value(default.clone(), inner1.map(|v| vec![v])).parse(input)
68            }
69            crate::parser::config::ElementBehavior::Map(f) => {
70                let (i, o) = inner.parse(input)?;
71                let mut f1 = (**f).borrow_mut();
72                let mapped = vec![(f1.as_mut())(o)];
73                Ok((i, mapped))
74            }
75            crate::parser::config::ElementBehavior::FlatMap(f) => {
76                let (i, o) = inner.parse(input)?;
77                let mut f1 = (**f).borrow_mut();
78                let mapped = (f1.as_mut())(o);
79                Ok((i, mapped))
80            }
81        }
82    }
83}
84
85pub(crate) fn conditional_block_unit<'a, P>(
86    behavior: crate::parser::config::ElementBehavior<Block>,
87    mut inner: P,
88) -> impl Parser<&'a str, Output = Vec<()>, Error = nom::error::Error<&'a str>>
89where
90    P: Parser<&'a str, Output = (), Error = nom::error::Error<&'a str>>,
91{
92    let behavior: crate::parser::config::ElementBehavior<()> = match behavior {
93        super::config::ElementBehavior::Parse => super::config::ElementBehavior::Parse,
94        super::config::ElementBehavior::Ignore => super::config::ElementBehavior::Ignore,
95        super::config::ElementBehavior::Skip => super::config::ElementBehavior::Skip,
96        super::config::ElementBehavior::Map(_) => super::config::ElementBehavior::Parse,
97        super::config::ElementBehavior::FlatMap(_) => super::config::ElementBehavior::Parse,
98    };
99    move |input: &'a str| {
100        let inner1 = |s: &'a str| inner.parse(s);
101        conditional(behavior.clone(), vec![()], inner1).parse(input)
102    }
103}
104
105pub(crate) fn conditional_inline_unit<'a, P>(
106    behavior: crate::parser::config::ElementBehavior<Inline>,
107    mut inner: P,
108) -> impl Parser<&'a str, Output = Vec<()>, Error = nom::error::Error<&'a str>>
109where
110    P: Parser<&'a str, Output = (), Error = nom::error::Error<&'a str>>,
111{
112    let behavior: crate::parser::config::ElementBehavior<()> = match behavior {
113        super::config::ElementBehavior::Parse => super::config::ElementBehavior::Parse,
114        super::config::ElementBehavior::Ignore => super::config::ElementBehavior::Ignore,
115        super::config::ElementBehavior::Skip => super::config::ElementBehavior::Skip,
116        super::config::ElementBehavior::Map(_) => super::config::ElementBehavior::Parse,
117        super::config::ElementBehavior::FlatMap(_) => super::config::ElementBehavior::Parse,
118    };
119    move |input: &'a str| {
120        let inner1 = |s: &'a str| inner.parse(s);
121        conditional(behavior.clone(), vec![()], inner1).parse(input)
122    }
123}
124
125pub(crate) fn conditional_block<'a, P>(
126    behavior: crate::parser::config::ElementBehavior<Block>,
127    mut inner: P,
128) -> impl Parser<&'a str, Output = Vec<Block>, Error = nom::error::Error<&'a str>>
129where
130    P: Parser<&'a str, Output = Block, Error = nom::error::Error<&'a str>>,
131{
132    move |input: &'a str| {
133        let inner1 = |s: &'a str| inner.parse(s);
134        conditional(behavior.clone(), vec![Block::Empty], inner1).parse(input)
135    }
136}
137
138pub(crate) fn conditional_inline<'a, P>(
139    behavior: crate::parser::config::ElementBehavior<Inline>,
140    mut inner: P,
141) -> impl Parser<&'a str, Output = Vec<Inline>, Error = nom::error::Error<&'a str>>
142where
143    P: Parser<&'a str, Output = Inline, Error = nom::error::Error<&'a str>>,
144{
145    move |input: &'a str| {
146        let inner1 = |s: &'a str| inner.parse(s);
147        conditional(behavior.clone(), vec![Inline::Empty], inner1).parse(input)
148    }
149}
150
151pub(crate) fn conditional_block_vec<'a, P>(
152    behavior: crate::parser::config::ElementBehavior<Block>,
153    mut inner: P,
154) -> impl Parser<&'a str, Output = Vec<Block>, Error = nom::error::Error<&'a str>>
155where
156    P: Parser<&'a str, Output = Vec<Block>, Error = nom::error::Error<&'a str>>,
157{
158    move |input: &'a str| {
159        let mut inner1 = |s: &'a str| inner.parse(s);
160        match &behavior {
161            crate::parser::config::ElementBehavior::Ignore => fail().parse(input),
162            crate::parser::config::ElementBehavior::Parse => inner1(input),
163            crate::parser::config::ElementBehavior::Skip => {
164                let (remaining, _) = inner1(input)?;
165                Ok((remaining, vec![Block::Empty]))
166            }
167            crate::parser::config::ElementBehavior::Map(_) => {
168                // Map behavior doesn't make sense for Vec<Block>, just parse normally
169                inner1(input)
170            }
171            crate::parser::config::ElementBehavior::FlatMap(_) => {
172                // FlatMap behavior doesn't make sense for Vec<Block>, just parse normally
173                inner1(input)
174            }
175        }
176    }
177}