Skip to content

Commit

Permalink
Expose the Either parser
Browse files Browse the repository at this point in the history
This will make it easier to build Parser implementations without having
to implement the trait manually
  • Loading branch information
Geal committed Feb 8, 2025
1 parent a44b52e commit 5534e57
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 67 deletions.
84 changes: 18 additions & 66 deletions benchmarks/benches/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ use codspeed_criterion_compat::*;
use nom::{
branch::alt,
bytes::{tag, take},
character::{anychar, char, multispace0, none_of},
combinator::{map, map_opt, map_res, value, verify},
character::{char, multispace0, none_of},
combinator::{map, map_opt, map_res, success, value, verify},
error::{Error, ErrorKind, FromExternalError, ParseError},
multi::{fold, separated_list0},
number::double,
number::recognize_float,
number::{double, recognize_float},
sequence::{delimited, preceded, separated_pair},
Check, Complete, Emit, IResult, Mode, OutputM, Parser,
Check, Complete, Either, Emit, IResult, OutputM, Parser,
};
use nom_language::error::VerboseError;

Expand Down Expand Up @@ -68,69 +67,22 @@ fn character<
'a,
E: ParseError<&'a str> + FromExternalError<&'a str, ParseIntError> + FromExternalError<&'a str, ()>,
>() -> impl Parser<&'a str, Output = char, Error = E> {
Character { e: PhantomData }
/*let (input, c) = none_of("\"")(input)?;
if c == '\\' {
alt((
map_res(anychar, |c| {
Ok(match c {
'"' | '\\' | '/' => c,
'b' => '\x08',
'f' => '\x0C',
'n' => '\n',
'r' => '\r',
't' => '\t',
_ => return Err(()),
})
}),
preceded(char('u'), unicode_escape()),
))
.parse(input)
} else {
Ok((input, c))
}*/
}

struct Character<E> {
e: PhantomData<E>,
}

impl<'a, E> Parser<&'a str> for Character<E>
where
E: ParseError<&'a str>
+ FromExternalError<&'a str, ParseIntError>
+ FromExternalError<&'a str, ()>,
{
type Output = char;

type Error = E;

fn process<OM: nom::OutputMode>(
&mut self,
input: &'a str,
) -> nom::PResult<OM, &'a str, Self::Output, Self::Error> {
let (input, c): (&str, char) =
none_of("\"").process::<OutputM<Emit, OM::Error, OM::Incomplete>>(input)?;
if c == '\\' {
alt((
map_res(anychar, |c| {
Ok(match c {
'"' | '\\' | '/' => c,
'b' => '\x08',
'f' => '\x0C',
'n' => '\n',
'r' => '\r',
't' => '\t',
_ => return Err(()),
})
}),
preceded(char('u'), unicode_escape()),
))
.process::<OM>(input)
none_of("\"").flat_map(|c| {
if c != '\\' {
Either::Left(success(c))

Check warning on line 72 in benchmarks/benches/json.rs

View check run for this annotation

Codecov / codecov/patch

benchmarks/benches/json.rs#L70-L72

Added lines #L70 - L72 were not covered by tests
} else {
Ok((input, OM::Output::bind(|| c)))
Either::Right(alt((
value('\\', tag("\\")),
value('\"', tag("\"")),
value('\n', tag("n")),
value('\r', tag("r")),
value('\t', tag("t")),
value('\x08', tag("b")),
value('\x0C', tag("f")),
preceded(char('u'), unicode_escape()),

Check warning on line 82 in benchmarks/benches/json.rs

View check run for this annotation

Codecov / codecov/patch

benchmarks/benches/json.rs#L74-L82

Added lines #L74 - L82 were not covered by tests
)))
}
}
})
}

fn string<
Expand Down
4 changes: 3 additions & 1 deletion src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,8 +781,10 @@ impl<
}

/// Alternate between two Parser implementations with the same result type.
pub(crate) enum Either<F, G> {
pub enum Either<F, G> {
/// Left parser alternative
Left(F),
/// Right parser alternative
Right(G),
}

Expand Down

0 comments on commit 5534e57

Please sign in to comment.