From 5534e57d99e33d676f3d06a58ecfe096da774edb Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Sat, 8 Feb 2025 16:03:10 +0100 Subject: [PATCH] Expose the Either parser This will make it easier to build Parser implementations without having to implement the trait manually --- benchmarks/benches/json.rs | 84 ++++++++------------------------------ src/internal.rs | 4 +- 2 files changed, 21 insertions(+), 67 deletions(-) diff --git a/benchmarks/benches/json.rs b/benchmarks/benches/json.rs index 805f4d50..aa210b8b 100644 --- a/benchmarks/benches/json.rs +++ b/benchmarks/benches/json.rs @@ -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; @@ -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: PhantomData, -} - -impl<'a, E> Parser<&'a str> for Character -where - E: ParseError<&'a str> - + FromExternalError<&'a str, ParseIntError> - + FromExternalError<&'a str, ()>, -{ - type Output = char; - - type Error = E; - - fn process( - &mut self, - input: &'a str, - ) -> nom::PResult { - let (input, c): (&str, char) = - none_of("\"").process::>(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::(input) + none_of("\"").flat_map(|c| { + if c != '\\' { + Either::Left(success(c)) } 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()), + ))) } - } + }) } fn string< diff --git a/src/internal.rs b/src/internal.rs index 94ed7c85..5bbc6223 100644 --- a/src/internal.rs +++ b/src/internal.rs @@ -781,8 +781,10 @@ impl< } /// Alternate between two Parser implementations with the same result type. -pub(crate) enum Either { +pub enum Either { + /// Left parser alternative Left(F), + /// Right parser alternative Right(G), }