函数 `impl Parser` 特征无法与 nom 中的 `alt` 组合器一起使用

问题描述 投票:0回答:1

我使用

alt
nom
函数为机器人命令构建解析器,即示例中的
parse_command

# src/main.rs
use nom::{
  IResult,
  bytes::complete::{tag},
  branch::alt,
  combinator::map,
};

#[derive(Debug, PartialEq)]
pub enum Command {
    Foo(),
    Bar(),
}

pub fn parse_command(input: &str) -> IResult<&str, Command> {
    alt((
        parse_foo,
        parse_bar,
    ))(input)
}

fn parse_foo(input: &str) -> IResult<&str, Command> {
    map(tag("!bar"), |_| Command::Bar())(input)
}

fn parse_bar(input: &str) -> IResult<&str, Command> {
    map(tag("!foo"), |_| Command::Foo())(input)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_bar() {
        let s = "!bar";
        let (_, result) = parse_command(s).unwrap();
        assert_eq!(result, Command::Bar());
    }

    #[test]
    fn test_parse_foo() {
        let s = "!foo";
        let (_, result) = parse_command(s).unwrap();
        assert_eq!(result, Command::Foo());
    }
}

这个效果很好。然而,在阅读 examples 时,我的印象是我可以更新

parse_bar
parse_foo
函数的签名,如下所示:

use nom::{
    Parser,
    error::Error,
};

fn parse_foo<'a>() -> impl Parser<&'a str, Command, Error<&'a str>> {
    map(tag("!bar"), |_| Command::Bar())
}

fn parse_bar<'a>() -> impl Parser<&'a str, Command, Error<&'a str>> {
    map(tag("!foo"), |_| Command::Foo())
}

但是,编译器对我尖叫:

error[E0593]: function is expected to take 1 argument, but it takes 0 arguments
  --> src/main.rs:18:9
   |
17 |     alt((
   |     --- required by a bound introduced by this call
18 |         parse_foo,
   |         ^^^^^^^^^ expected function that takes 1 argument
...
24 | fn parse_foo<'a>() -> impl Parser<&'a str, Command, Error<&'a str>> {
   | ------------------------------------------------------------------- takes 0 arguments
   |
   = note: required for `fn() -> impl Parser<&str, Command, nom::error::Error<&str>> {parse_foo::<'_>}` to implement `Parser<_, _, _>`
   = note: required for `(fn() -> impl Parser<&str, Command, nom::error::Error<&str>> {parse_foo::<'_>}, fn() -> impl Parser<&str, Command, nom::error::Error<&str>> {parse_bar::<'_>})` to implement `nom::branch::Alt<_, _, _>`
note: required by a bound in `alt`
  --> /home/pamplemousse/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nom-7.1.3/src/branch/mod.rs:47:49
   |
47 | pub fn alt<I: Clone, O, E: ParseError<I>, List: Alt<I, O, E>>(
   |                                                 ^^^^^^^^^^^^ required by this bound in `alt`

[... and same error for `parse_bar`...]

我对使用

Parser
特性来实现此类功能的期望是否错误?如果没有,我错过/误解了什么以便我更新的代码可以工作?

rust parser-combinators nom
1个回答
0
投票

您的第二个示例失败了,没有显示对

parse_command
的调用。如果它与第一个有效的调用完全相同,那么问题在于您没有调用函数来返回实际的
Parser
实现,而是将
fn
传递给它期望的
Parser
实现.

所以修复应该是:

pub fn parse_command(input: &str) -> IResult<&str, Command> {
    alt((
        parse_foo(), 
        parse_bar(),
    ))(input)
}

需要明确的是,区别在于

parse_foo()
parse_foo
,与
parse_bar
类似。

© www.soinside.com 2019 - 2024. All rights reserved.