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?