1

我编写了以下 nom 解析器代码:

use nom::character::complete::digit1;
use nom::combinator::map_res;
use nom::error::Error;
use nom::sequence::tuple;
use nom::Err;

type E<'a> = Err<Error<&'a str>>;

fn parse_double_int(input: &str) -> Option<(i32, i32)> {
    let num = map_res(digit1, |s: &str| s.parse::<i32>());
    let mut pair = tuple((num, num));
    let res: Result<_, E> = pair(&input.trim());

    match res {
        Ok((_, (a, b))) => Some((a, b)),
        Err(_) => None,
    }
}

错误:

error[E0382]: use of moved value: `num`
  --> src\lib.rs:11:32
   |
10 |     let num = map_res(digit1, |s: &str| s.parse::<i32>());
   |         --- move occurs because `num` has type `impl FnMut<(&str,)>`, which does not implement the `Copy` trait
11 |     let mut pair = tuple((num, num));
   |                           ---  ^^^ value used here after move
   |                           |
   |                           value moved here

For more information about this error, try `rustc --explain E0382`.

如何重用我在本地定义的解析器?

4

2 回答 2

3

map_res返回一个FnMut。你不能移动两次FnMut因为FnMut没有实现Copy,而不是明显的解决方案是借用它,但你不能导致Parserrequiremut并且你不能有多个可变借用。所以最后一个选项是实现一个Parser实现Copy或可以轻松创建的:

将实现副本的闭包包装在FnMut内部:Fn

let num = |input| map_res(digit1, |s: &str| s.parse::<i32>())(input);

创建一个函数:

fn num(input: &str) -> IResult<&str, i32> {
  map_res(digit1, |s: &str| s.parse::<i32>())(input)
}
于 2021-12-05T19:18:32.717 回答
1

您正在“移动值”,这意味着 Rust 赋予您的值 num 的所有权,然后在它完成时释放它(删除它),您可以尝试让您的函数使用 &num 表示法借用该值,或者克隆变量,如果struct 实现了克隆特征。这里有一个类似的问题,我无法仅使用代码段重新创建您的问题,但希望这可以为您提供足够的信息来找到解决方案!

于 2021-12-05T17:23:44.743 回答