22
33use std:: convert:: Infallible ;
44
5- use nom:: { IResult , InputLength } ;
5+ use nom:: { AsChar , IResult , InputLength , InputTakeAtPosition } ;
66
77pub ( crate ) type ErrorList = Vec < LenientErrorInternal > ;
88pub ( crate ) type JResult < I , O > = IResult < I , ( O , ErrorList ) , Infallible > ;
99
1010/// An error, with an end-of-string based offset
11+ #[ derive( Debug ) ]
1112pub ( crate ) struct LenientErrorInternal {
12- pos : usize ,
13- message : String ,
13+ pub pos : usize ,
14+ pub message : String ,
1415}
1516
1617/// A recoverable error and the position it happened at
18+ #[ derive( Debug , PartialEq ) ]
1719pub struct LenientError {
1820 pub pos : usize ,
1921 pub message : String ,
@@ -38,8 +40,6 @@ fn unwrap_infallible<T>(res: Result<T, nom::Err<Infallible>>) -> T {
3840// when rfcs#1733 get stabilized, this can make things clearer
3941// trait InfallibleParser<I, O> = nom::Parser<I, (O, ErrorList), std::convert::Infallible>;
4042
41- // TODO space0 and space1: space0 can't fail, space1 can parse nothing but reports missing space
42-
4343/// A variant of the classical `opt` parser, except it returns an infallible error type.
4444///
4545/// It's less generic than the original to ease type resolution in the rest of the code.
@@ -54,6 +54,53 @@ where F: nom::Parser<I, O, nom::error::Error<I>> {
5454 }
5555}
5656
57+ pub ( crate ) fn opt_i_err < ' a , I : Clone + InputLength , O , F > (
58+ mut f : F ,
59+ message : impl ToString + ' a ,
60+ ) -> impl FnMut ( I ) -> JResult < I , Option < O > > + ' a
61+ where
62+ F : nom:: Parser < I , O , nom:: error:: Error < I > > + ' a ,
63+ {
64+ move |input : I | {
65+ let i = input. clone ( ) ;
66+ match f. parse ( input) {
67+ Ok ( ( i, o) ) => Ok ( ( i, ( Some ( o) , Vec :: new ( ) ) ) ) ,
68+ Err ( _) => {
69+ let errs = vec ! [ LenientErrorInternal {
70+ pos: i. input_len( ) ,
71+ message: message. to_string( ) ,
72+ } ] ;
73+ Ok ( ( i, ( None , errs) ) )
74+ }
75+ }
76+ }
77+ }
78+
79+ pub ( crate ) fn space0_infallible < T > ( input : T ) -> JResult < T , T >
80+ where
81+ T : InputTakeAtPosition + Clone ,
82+ <T as InputTakeAtPosition >:: Item : AsChar + Clone ,
83+ {
84+ opt_i ( nom:: character:: complete:: space0) ( input)
85+ . map ( |( left, ( spaces, errors) ) | ( left, ( spaces. expect ( "space0 can't fail" ) , errors) ) )
86+ }
87+
88+ pub ( crate ) fn space1_infallible < T > ( input : T ) -> JResult < T , Option < T > >
89+ where
90+ T : InputTakeAtPosition + Clone + InputLength ,
91+ <T as InputTakeAtPosition >:: Item : AsChar + Clone ,
92+ {
93+ opt_i ( nom:: character:: complete:: space1) ( input) . map ( |( left, ( spaces, mut errors) ) | {
94+ if spaces. is_none ( ) {
95+ errors. push ( LenientErrorInternal {
96+ pos : left. input_len ( ) ,
97+ message : "missing space" . to_string ( ) ,
98+ } )
99+ }
100+ ( left, ( spaces, errors) )
101+ } )
102+ }
103+
57104pub ( crate ) fn fallible < I , O , E : nom:: error:: ParseError < I > , F > (
58105 mut f : F ,
59106) -> impl FnMut ( I ) -> IResult < I , O , E >
@@ -206,30 +253,30 @@ where
206253 F : nom:: Parser < I , ( O , ErrorList ) , Infallible > ,
207254 G : nom:: Parser < I , ( O2 , ErrorList ) , Infallible > ,
208255{
209- move |mut i : I | {
256+ move |i : I | {
210257 let mut res: Vec < O > = Vec :: new ( ) ;
211258 let mut errors: ErrorList = Vec :: new ( ) ;
212259
213- let ( i1 , ( o, mut err) ) = unwrap_infallible ( f. parse ( i. clone ( ) ) ) ;
260+ let ( mut i , ( o, mut err) ) = unwrap_infallible ( f. parse ( i. clone ( ) ) ) ;
214261 errors. append ( & mut err) ;
215262 res. push ( o) ;
216- i = i1;
217263
218264 loop {
219- let len = i. input_len ( ) ;
220- let ( i1, ( _, mut err) ) = unwrap_infallible ( sep. parse ( i. clone ( ) ) ) ;
221- errors. append ( & mut err) ;
265+ let ( i_sep_parsed, ( _, mut err_sep) ) = unwrap_infallible ( sep. parse ( i. clone ( ) ) ) ;
266+ let len_before = i_sep_parsed. input_len ( ) ;
222267
223- let ( i2, ( o, mut err) ) = unwrap_infallible ( f. parse ( i1. clone ( ) ) ) ;
268+ let ( i_elem_parsed, ( o, mut err_elem) ) =
269+ unwrap_infallible ( f. parse ( i_sep_parsed. clone ( ) ) ) ;
224270
225271 // infinite loop check: the parser must always consume
226272 // if we consumed nothing here, don't produce an element.
227- if i2 . input_len ( ) == len {
228- return Ok ( ( i1 , ( res, errors) ) ) ;
273+ if i_elem_parsed . input_len ( ) == len_before {
274+ return Ok ( ( i , ( res, errors) ) ) ;
229275 }
230276 res. push ( o) ;
231- errors. append ( & mut err) ;
232- i = i2;
277+ errors. append ( & mut err_sep) ;
278+ errors. append ( & mut err_elem) ;
279+ i = i_elem_parsed;
233280 }
234281 }
235282}
@@ -269,7 +316,7 @@ macro_rules! alt_trait_impl(
269316 fn choice( & mut self , input: Input ) -> Option <JResult <Input , Output >> {
270317 match self . 0.0 . parse( input. clone( ) ) {
271318 Err ( _) => alt_trait_inner!( 1 , self , input, $( $id_cond $id) ,+) ,
272- Ok ( ( i1 , _) ) => Some ( self . 0.1 . parse( i1 ) ) ,
319+ Ok ( ( input_left , _) ) => Some ( self . 0.1 . parse( input_left ) ) ,
273320 }
274321 }
275322 }
@@ -280,7 +327,7 @@ macro_rules! alt_trait_inner(
280327 ( $it: tt, $self: expr, $input: expr, $head_cond: ident $head: ident, $( $id_cond: ident $id: ident) ,+) => (
281328 match $self. $it. 0 . parse( $input. clone( ) ) {
282329 Err ( _) => succ!( $it, alt_trait_inner!( $self, $input, $( $id_cond $id) ,+) ) ,
283- Ok ( ( i1 , _) ) => Some ( $self. $it. 1 . parse( i1 ) ) ,
330+ Ok ( ( input_left , _) ) => Some ( $self. $it. 1 . parse( input_left ) ) ,
284331 }
285332 ) ;
286333 ( $it: tt, $self: expr, $input: expr, $head_cond: ident $head: ident) => (
0 commit comments