Why is this returning an error (implementing Choice parser combinator)?

36 views Asked by At

I'm trying to implement a parser in functional way, specifically the choice parser combinator. Choice is a function that takes in a list of parsers and returns a closure that takes in the input, applies the parsers, and returns the first one that succeeds.

Here is the implementation of choice function

fn successful<'a, T, F>(input: &'a [u8], choices: &'a [F]) -> Result<(T, &'a [u8])>
where
    F: Fn(&'a [u8]) -> Result<(T, &'a [u8])>,
{
    if let Some(parser) = choices.get(0) {
        match parser(input) {
            Ok(result) => Ok(result),
            Err(_) => successful(input, &choices[1..]),
        }
    } else {
        let result = Error::Generic("no choices left".to_string());
        Err(result)
    }
}

pub fn choice<'a, T, F>(choices: &'a [F]) -> impl Fn(&'a [u8]) -> Result<(T, &'a [u8])>
where
    F: Fn(&'a [u8]) -> Result<(T, &'a [u8])>,
{
    |input: &[u8]| successful(input, choices)
}

And with that, I implemented two parsers, digit and alpha

fn digit(input: &[u8]) -> Result<(&u8, &[u8])> {
    if let Some(byte) = input.first() {
        if byte.is_ascii_digit() {
            Ok((byte, &input[1..]))
        } else {
            let result = Error::Generic(f!("expected digit, got '{}'", *byte as char));

            Err(result)
        }
    } else {
        let result = Error::Generic("expected digit, got none".to_string());

        Err(result)
    }
}

fn alpha(input: &[u8]) -> Result<(&u8, &[u8])> {
    if let Some(byte) = input.first() {
        if byte.is_ascii_alphabetic() {
            Ok((byte, &input[1..]))
        } else {
            let result = Error::Generic(f!("expected alpha, got '{}'", *byte as char));

            Err(result)
        }
    } else {
        let result = Error::Generic("expected alpha, got none".to_string());

        Err(result)
    }
}

So given that, I wanted to implement alphanumeric parser, which uses choice to parse either alpha or digit

fn alphanumeric(input: &[u8]) -> Result<(&u8, &[u8])> {
    choice(&[digit, alpha])(input)
}

However, I receive this error

error[E0308]: mismatched types
  --> src\main.rs:45:12
   |
45 |     choice(&[digit, alpha])(input)
   |     ------ ^^^^^^^^^^^^^^^ expected `&[fn(&[u8]) -> ... {digit}]`, found `&[fn(&[u8]) -> Result<..., ...>; 2]`
   |     |
   |     arguments to this function are incorrect
   |
   = note: expected reference `&[for<'a> fn(&'a [u8]) -> std::result::Result<(&'a u8, &'a [u8]), shiki::error::Error> {digit}]`
              found reference `&[for<'a> fn(&'a [u8]) -> std::result::Result<(&'a u8, &'a [u8]), shiki::error::Error>; 2]`
note: function defined here
  --> D:\John Mark\Code\shiki\src\parser\combinator\choice.rs:21:8
   |
21 | pub fn choice<'a, T, F>(choices: &'a [F]) -> impl Fn(&'a [u8]) -> Result<(T, &'a [u8])>

Any ideas about this?

0

There are 0 answers