我希望创建一个类似alt
的函数,它不是从元组中使用解析器,而是从迭代器中使用解析器。
我遇到的问题是参数化解析器上的绑定FnMut
。Parser
是为FnMut
实现的,而不是Fn
。FnMut
是不可克隆的,这意味着我必须把它放在某种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))
}
}
型
是否有其他可行的解决方案?
1条答案
按热度按时间bvjveswy1#
假设你想要的是
alt
的实际行为,而不是take
的不同行为,你可以这样写alt_many
:字符串