使用nom的Parser trait实现解析器时与alt组合器兼容问题
问题原因与解决方案
你的核心问题是对nom中Parser trait的使用方式理解有误:当前parse_foo和parse_bar是返回Parser实例的无参函数,但alt期望接收的是已经实现了Parser trait的类型实例,而非“返回Parser的函数”本身。直接将函数名传给alt时,nom会尝试将这个无参函数当作Parser来适配,但Parser trait要求解析器能接收输入参数,因此编译器报错参数数量不匹配。
修正方案
方案一:直接调用无参函数获取Parser实例(最直接)
修改parse_command函数,在传入alt前调用parse_foo()和parse_bar(),得到实际的Parser实例:
pub fn parse_command(input: &str) -> IResult<&str, Command> { alt(( parse_foo(), parse_bar(), ))(input) }
方案二:定义Parser静态常量(更简洁)
如果不需要动态生成解析器逻辑,直接将解析器定义为静态常量,避免函数调用的开销:
use nom::{Parser, bytes::complete::tag, combinator::map, error::Error}; #[derive(Debug, PartialEq)] pub enum Command { Foo(), Bar(), } static PARSE_FOO: impl for<'a> Parser<&'a str, Command, Error<&'a str>> = map(tag("!foo"), |_| Command::Foo()); static PARSE_BAR: impl for<'a> Parser<&'a str, Command, Error<&'a str>> = map(tag("!bar"), |_| Command::Bar()); pub fn parse_command(input: &str) -> IResult<&str, Command> { alt(( PARSE_FOO, PARSE_BAR, ))(input) }
额外修正:逻辑一致性问题
你原代码中parse_foo解析!bar返回Command::Bar(),parse_bar解析!foo返回Command::Foo(),逻辑反向不符合命名直觉,建议修正为:
fn parse_foo<'a>() -> impl Parser<&'a str, Command, Error<&'a str>> { map(tag("!foo"), |_| Command::Foo()) } fn parse_bar<'a>() -> impl Parser<&'a str, Command, Error<&'a str>> { map(tag("!bar"), |_| Command::Bar()) }
内容的提问来源于stack exchange,提问作者Pamplemousse
相关产品推荐
相关产品推荐

