Nom 5 and returning a custom error

I have just started using Nom 5. Its been rough but I am getting there.
I have paser that detects variable names ie alpha character and _ etc.
My code is like the following

fn take_first_ident_char<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {

    let first_chars = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    let c = take(1usize)(i);
    
    match c {
        Ok((remaining_input, character)) => {
            if first_chars.contains(character) {
                return Ok((i, character));  // Return original str don't return remaining input
            }

            return Ok(("", ""));
            //Help
            //return Err(());
            //return Err(Error("ident lacks a valid character for the first position"));
            //return Err(VerboseError<&str>("ident lacks a valid character for the first position"));
        },
		Err(e) => Err(e)
    }
}

/// Must start with a letter or an underscore, can be followed by letters, digits or underscores.
fn ident<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
  let remaining_chars = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

  preceded(take_first_ident_char, take_while(move |c| remaining_chars.contains(c)))(i)
}

What I am missing is what kind of error I should return in take_first_ident_char if the first character is not valid.
I am return return Ok(("", "")); as I can't get any error return to compile.
What is the best practive here for the latest Nom ?

Thanks

nom::error::ParseError - Rust

You can do nom::error::ParseError::from_error_kind(i, nom::error::ErrorKind::OneOf) to create an error value manually.

However, it would be better use only standard combinators.

use nom::{
  bytes::complete::is_a,
  character::complete::one_of,
  combinator::recognize,
  sequence::preceded,
};

fn ident<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
  let REMAINING_CHARS: &str = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  let FIRST_CHARS: &str = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

  // Returns whole strings matched by the given parser.
  recognize(
    // Runs the first parser, if succeeded then runs second, and returns the second result.
    // Note that returned ok value of `preceded()` is ignored by `recognize()`.
    preceded(
      // Parses a single character contained in the given string.
      one_of(FIRST_CHARS),
      // Parses the longest slice consisting of the given characters
      is_a(REMAINING_CHARS),
    )
  )(i)
}

(I didn't tested this, but it should be like this.)

Nom provides quite a lot of parsers including combinators, and some of their names are not so intuitive for me... :confounded:

1 Like

Thanks.
Yeah after looking at docs for quite a while I still didn't know about one_of :slight_smile:
More learning todo.