1use std::convert::Infallible;
4
5use nom::{AsChar, IResult, InputLength, InputTakeAtPosition};
6use serde::Serialize;
7
8pub(crate) type ErrorList = Vec<LenientErrorInternal>;
9pub(crate) type JResult<I, O> = IResult<I, (O, ErrorList), Infallible>;
10
11#[derive(Debug)]
13pub(crate) struct LenientErrorInternal {
14 pub pos: usize,
15 pub message: String,
16}
17
18#[derive(Debug, PartialEq, Serialize)]
20#[serde(rename_all = "snake_case")]
21pub struct LenientError {
22 pub pos: usize,
23 pub message: String,
24}
25
26impl LenientError {
27 pub(crate) fn from_internal(internal: LenientErrorInternal, str_len: usize) -> LenientError {
28 LenientError {
29 pos: str_len - internal.pos,
30 message: internal.message,
31 }
32 }
33}
34
35fn unwrap_infallible<T>(res: Result<T, nom::Err<Infallible>>) -> T {
36 match res {
37 Ok(val) => val,
38 Err(_) => unreachable!(),
39 }
40}
41
42pub(crate) fn opt_i<I: Clone, O, F>(mut f: F) -> impl FnMut(I) -> JResult<I, Option<O>>
49where F: nom::Parser<I, O, nom::error::Error<I>> {
50 move |input: I| {
51 let i = input.clone();
52 match f.parse(input) {
53 Ok((i, o)) => Ok((i, (Some(o), Vec::new()))),
54 Err(_) => Ok((i, (None, Vec::new()))),
55 }
56 }
57}
58
59pub(crate) fn opt_i_err<'a, I: Clone + InputLength, O, F>(
60 mut f: F,
61 message: impl ToString + 'a,
62) -> impl FnMut(I) -> JResult<I, Option<O>> + 'a
63where
64 F: nom::Parser<I, O, nom::error::Error<I>> + 'a,
65{
66 move |input: I| {
67 let i = input.clone();
68 match f.parse(input) {
69 Ok((i, o)) => Ok((i, (Some(o), Vec::new()))),
70 Err(_) => {
71 let errs = vec![LenientErrorInternal {
72 pos: i.input_len(),
73 message: message.to_string(),
74 }];
75 Ok((i, (None, errs)))
76 }
77 }
78 }
79}
80
81pub(crate) fn space0_infallible<T>(input: T) -> JResult<T, T>
82where
83 T: InputTakeAtPosition + Clone,
84 <T as InputTakeAtPosition>::Item: AsChar + Clone,
85{
86 opt_i(nom::character::complete::multispace0)(input)
87 .map(|(left, (spaces, errors))| (left, (spaces.expect("multispace0 can't fail"), errors)))
88}
89
90pub(crate) fn space1_infallible<T>(input: T) -> JResult<T, Option<T>>
91where
92 T: InputTakeAtPosition + Clone + InputLength,
93 <T as InputTakeAtPosition>::Item: AsChar + Clone,
94{
95 opt_i(nom::character::complete::multispace1)(input).map(|(left, (spaces, mut errors))| {
96 if spaces.is_none() {
97 errors.push(LenientErrorInternal {
98 pos: left.input_len(),
99 message: "missing space".to_string(),
100 })
101 }
102 (left, (spaces, errors))
103 })
104}
105
106pub(crate) fn fallible<I, O, E: nom::error::ParseError<I>, F>(
107 mut f: F,
108) -> impl FnMut(I) -> IResult<I, O, E>
109where F: nom::Parser<I, (O, ErrorList), Infallible> {
110 use nom::Err;
111 move |input: I| match f.parse(input) {
112 Ok((input, (output, _err))) => Ok((input, output)),
113 Err(Err::Incomplete(needed)) => Err(Err::Incomplete(needed)),
114 Err(Err::Error(val)) | Err(Err::Failure(val)) => match val {},
117 }
118}
119
120pub(crate) fn delimited_infallible<I, O1, O2, O3, F, G, H>(
121 mut first: F,
122 mut second: G,
123 mut third: H,
124) -> impl FnMut(I) -> JResult<I, O2>
125where
126 F: nom::Parser<I, (O1, ErrorList), Infallible>,
127 G: nom::Parser<I, (O2, ErrorList), Infallible>,
128 H: nom::Parser<I, (O3, ErrorList), Infallible>,
129{
130 move |input: I| {
131 let (input, (_, mut err)) = first.parse(input)?;
132 let (input, (o2, mut err2)) = second.parse(input)?;
133 err.append(&mut err2);
134 let (input, (_, mut err3)) = third.parse(input)?;
135 err.append(&mut err3);
136 Ok((input, (o2, err)))
137 }
138}
139
140pub(crate) fn nothing(i: &str) -> JResult<&str, ()> {
142 Ok((i, ((), Vec::new())))
143}
144
145pub(crate) trait TupleInfallible<I, O> {
146 fn parse(&mut self, input: I) -> JResult<I, O>;
148}
149
150impl<Input, Output, F: nom::Parser<Input, (Output, ErrorList), Infallible>>
151 TupleInfallible<Input, (Output,)> for (F,)
152{
153 fn parse(&mut self, input: Input) -> JResult<Input, (Output,)> {
154 self.0.parse(input).map(|(i, (o, e))| (i, ((o,), e)))
155 }
156}
157
158macro_rules! tuple_trait(
160 ($name1:ident $ty1:ident, $name2: ident $ty2:ident, $($name:ident $ty:ident),*) => (
161 tuple_trait!(__impl $name1 $ty1, $name2 $ty2; $($name $ty),*);
162 );
163 (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident, $($name2:ident $ty2:ident),*) => (
164 tuple_trait_impl!($($name $ty),+);
165 tuple_trait!(__impl $($name $ty),+ , $name1 $ty1; $($name2 $ty2),*);
166 );
167 (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident) => (
168 tuple_trait_impl!($($name $ty),+);
169 tuple_trait_impl!($($name $ty),+, $name1 $ty1);
170 );
171);
172
173macro_rules! tuple_trait_impl(
174 ($($name:ident $ty: ident),+) => (
175 impl<
176 Input: Clone, $($ty),+ ,
177 $($name: nom::Parser<Input, ($ty, ErrorList), Infallible>),+
178 > TupleInfallible<Input, ( $($ty),+ )> for ( $($name),+ ) {
179
180 fn parse(&mut self, input: Input) -> JResult<Input, ( $($ty),+ )> {
181 let mut error_list = Vec::new();
182 tuple_trait_inner!(0, self, input, (), error_list, $($name)+)
183 }
184 }
185 );
186);
187
188macro_rules! tuple_trait_inner(
189 ($it:tt, $self:expr, $input:expr, (), $error_list:expr, $head:ident $($id:ident)+) => ({
190 let (i, (o, mut err)) = $self.$it.parse($input.clone())?;
191 $error_list.append(&mut err);
192
193 succ!($it, tuple_trait_inner!($self, i, ( o ), $error_list, $($id)+))
194 });
195 ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $error_list:expr, $head:ident $($id:ident)+) => ({
196 let (i, (o, mut err)) = $self.$it.parse($input.clone())?;
197 $error_list.append(&mut err);
198
199 succ!($it, tuple_trait_inner!($self, i, ($($parsed)* , o), $error_list, $($id)+))
200 });
201 ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $error_list:expr, $head:ident) => ({
202 let (i, (o, mut err)) = $self.$it.parse($input.clone())?;
203 $error_list.append(&mut err);
204
205 Ok((i, (($($parsed)* , o), $error_list)))
206 });
207);
208
209macro_rules! succ (
210 (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
211 (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
212 (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
213 (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
214 (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
215 (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
216 (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
217 (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
218 (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
219 (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
220 (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
221 (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
222 (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
223 (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
224 (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
225 (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
226 (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
227 (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
228 (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
229 (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
230 (20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
231);
232
233tuple_trait!(FnA A, FnB B, FnC C, FnD D, FnE E, FnF F, FnG G, FnH H, FnI I, FnJ J, FnK K, FnL L,
234 FnM M, FnN N, FnO O, FnP P, FnQ Q, FnR R, FnS S, FnT T, FnU U);
235
236impl<I> TupleInfallible<I, ()> for () {
240 fn parse(&mut self, input: I) -> JResult<I, ()> {
241 Ok((input, ((), Vec::new())))
242 }
243}
244
245pub(crate) fn tuple_infallible<I, O, List: TupleInfallible<I, O>>(
246 mut l: List,
247) -> impl FnMut(I) -> JResult<I, O> {
248 move |i: I| l.parse(i)
249}
250
251pub(crate) fn separated_list_infallible<I, O, O2, F, G>(
252 mut sep: G,
253 mut f: F,
254) -> impl FnMut(I) -> JResult<I, Vec<O>>
255where
256 I: Clone + InputLength,
257 F: nom::Parser<I, (O, ErrorList), Infallible>,
258 G: nom::Parser<I, (O2, ErrorList), Infallible>,
259{
260 move |i: I| {
261 let mut res: Vec<O> = Vec::new();
262 let mut errors: ErrorList = Vec::new();
263
264 let (mut i, (o, mut err)) = unwrap_infallible(f.parse(i.clone()));
265 errors.append(&mut err);
266 res.push(o);
267
268 loop {
269 let (i_sep_parsed, (_, mut err_sep)) = unwrap_infallible(sep.parse(i.clone()));
270 let len_before = i_sep_parsed.input_len();
271
272 let (i_elem_parsed, (o, mut err_elem)) =
273 unwrap_infallible(f.parse(i_sep_parsed.clone()));
274
275 if i_elem_parsed.input_len() == len_before {
278 return Ok((i, (res, errors)));
279 }
280 res.push(o);
281 errors.append(&mut err_sep);
282 errors.append(&mut err_elem);
283 i = i_elem_parsed;
284 }
285 }
286}
287
288pub(crate) trait Alt<I, O> {
289 fn choice(&mut self, input: I) -> Option<JResult<I, O>>;
291}
292
293macro_rules! alt_trait(
294 ($first_cond:ident $first:ident, $($id_cond:ident $id: ident),+) => (
295 alt_trait!(__impl $first_cond $first; $($id_cond $id),+);
296 );
297 (__impl $($current_cond:ident $current:ident),*; $head_cond:ident $head:ident, $($id_cond:ident $id:ident),+) => (
298 alt_trait_impl!($($current_cond $current),*);
299
300 alt_trait!(__impl $($current_cond $current,)* $head_cond $head; $($id_cond $id),+);
301 );
302 (__impl $($current_cond:ident $current:ident),*; $head_cond:ident $head:ident) => (
303 alt_trait_impl!($($current_cond $current),*);
304 alt_trait_impl!($($current_cond $current,)* $head_cond $head);
305 );
306);
307
308macro_rules! alt_trait_impl(
309 ($($id_cond:ident $id:ident),+) => (
310 impl<
311 Input: Clone, Output,
312 $(
313 $id_cond: nom::Parser<Input, (), ()>,
316 $id: nom::Parser<Input, (Output, ErrorList), Infallible>
317 ),+
318 > Alt<Input, Output> for ( $(($id_cond, $id),)+ ) {
319
320 fn choice(&mut self, input: Input) -> Option<JResult<Input, Output>> {
321 match self.0.0.parse(input.clone()) {
322 Err(_) => alt_trait_inner!(1, self, input, $($id_cond $id),+),
323 Ok((input_left, _)) => Some(self.0.1.parse(input_left)),
324 }
325 }
326 }
327 );
328);
329
330macro_rules! alt_trait_inner(
331 ($it:tt, $self:expr, $input:expr, $head_cond:ident $head:ident, $($id_cond:ident $id:ident),+) => (
332 match $self.$it.0.parse($input.clone()) {
333 Err(_) => succ!($it, alt_trait_inner!($self, $input, $($id_cond $id),+)),
334 Ok((input_left, _)) => Some($self.$it.1.parse(input_left)),
335 }
336 );
337 ($it:tt, $self:expr, $input:expr, $head_cond:ident $head:ident) => (
338 None
339 );
340);
341
342alt_trait!(A1 A, B1 B, C1 C, D1 D, E1 E, F1 F, G1 G, H1 H, I1 I, J1 J, K1 K,
343 L1 L, M1 M, N1 N, O1 O, P1 P, Q1 Q, R1 R, S1 S, T1 T, U1 U);
344
345pub(crate) fn alt_infallible<I: Clone, O, F, List: Alt<I, O>>(
350 mut l: List,
351 mut default: F,
352) -> impl FnMut(I) -> JResult<I, O>
353where
354 F: nom::Parser<I, (O, ErrorList), Infallible>,
355{
356 move |i: I| l.choice(i.clone()).unwrap_or_else(|| default.parse(i))
357}
358
359#[cfg(test)]
360mod tests {
361 use super::*;
362
363 #[test]
364 fn test_lenient_error_serialization() {
365 let error = LenientError {
366 pos: 42,
367 message: "test error message".to_string(),
368 };
369
370 assert_eq!(
371 serde_json::to_string(&error).unwrap(),
372 "{\"pos\":42,\"message\":\"test error message\"}"
373 );
374 }
375}