rust 有没有一种方法可以动态地`alt`一个解析器的迭代器?

vc9ivgsu  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(91)

我希望创建一个类似alt的函数,它不是从元组中使用解析器,而是从迭代器中使用解析器。
我遇到的问题是参数化解析器上的绑定FnMutParser是为FnMut实现的,而不是FnFnMut是不可克隆的,这意味着我必须把它放在某种Box中,然后可变地借用它。
以下是我的签名:

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

fn alt<I, O, E, P>(parsers: impl IntoIterator<Item = P>) -> impl Parser<I, O, E>
where
    P: Parser<I, O, E>
{
    move |input| {
        // implementation
    }
}

字符串
这个实现可以工作,但只有当一切都是可变的:

use nom::{error::ParseError, InputIter, InputTake, Parser};

pub fn alt_many<I, O, E, P>(mut parsers: Vec<&mut P>) -> impl Parser<I, O, E> + '_
where
    P: Parser<I, O, E>,
    I: InputIter + InputTake + Copy,
    E: ParseError<I>,
{
    move |mut input| {
        use nom::bytes::complete::take;
        use nom::combinator::fail;

        let mut value: Option<O> = None;

        for parser in &mut parsers {
            if let Ok((input_, o)) = parser.parse(input) {
                input = input_;
                value = Some(o);
                break;
            } else {
                (input, _) = take::<u8, I, E>(1)(input)?;
            };
        }

        value
            .map(|output| Ok((input, output)))
            .unwrap_or_else(|| fail::<I, O, E>(input))
    }
}


是否有其他可行的解决方案?

bvjveswy

bvjveswy1#

假设你想要的是alt的实际行为,而不是take的不同行为,你可以这样写alt_many

pub fn alt_many<I, O, E, P, Ps>(mut parsers: Ps) -> impl Parser<I, O, E>
where
    P: Parser<I, O, E>,
    I: Clone,
    for<'a> &'a mut Ps: IntoIterator<Item = &'a mut P>,
    E: ParseError<I>,
{
    move |input: I| { 
        for parser in &mut parsers {
            if let r@Ok(_) = parser.parse(input.clone()) {
                return r;
            }
        }
        nom::combinator::fail::<I, O, E>(input)
    }
}

字符串

相关问题