admin管理员组文章数量:1353453
I'd like to write a nom parser combinator that takes a generic parser inner
, builds two different variants of it using combinators that already exist in nom, and then tries them in say an alt
combinator. Conceptually, I'd like to do
alt((some_existing_combinator(inner), some_other_existing_combinator(inner)))
Of course, this doesn't work, because inner
isn't in general of a type that is Copy
(or even Clone
). From my understanding, no parser built from nom combinators is Copy
or Clone
. Thus, I'm clearly barking up the wrong tree here. How does one typically approach this kind of problem?
I'd like to write a nom parser combinator that takes a generic parser inner
, builds two different variants of it using combinators that already exist in nom, and then tries them in say an alt
combinator. Conceptually, I'd like to do
alt((some_existing_combinator(inner), some_other_existing_combinator(inner)))
Of course, this doesn't work, because inner
isn't in general of a type that is Copy
(or even Clone
). From my understanding, no parser built from nom combinators is Copy
or Clone
. Thus, I'm clearly barking up the wrong tree here. How does one typically approach this kind of problem?
1 Answer
Reset to default 1You basically have two options: wrap the whole delimited
thing in its own parsing function, which is Copy
; or create a zero-arg closure (or function) that creates one-off delimited
parsers each time you need one. The toy example below compiles.
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::{digit1, multispace0},
combinator::map_res,
multi::{many0, many1},
sequence::delimited,
IResult, Parser,
};
fn parser(s: &str) -> IResult<&str, i32> {
map_res((tag("num="), digit1), |(_, n): (_, &str)| n.parse::<i32>())
.parse(s)
}
// a fn, therefore Copy
fn my_delimited(s: &str) -> IResult<&str, i32> {
delimited(multispace0, parser, multispace0).parse(s)
}
fn main() {
// makes a fresh parser each time it's called
let make_inner = || delimited(multispace0, parser, multispace0);
let parser_1 = alt((many0(my_delimited), many1(my_delimited)));
let parser_2 = alt((many0(make_inner()), many1(make_inner())));
}
本文标签:
版权声明:本文标题:rust - Writing a nom parser combinator that tries various parsers built from a supplied parser and combinators - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1743896889a2557951.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
Clone
if their arguments are, or are evenCopy
if they're a plain old function (because all functions areCopy
). Why isn't yourinner: Clone
? – BallpointBen Commented Apr 1 at 10:57inner
isdelimited(multispace0, parser, multispace0)
, andparser
is in turn made up fromtuple
,map
,tag
and some number parsers included with nom, then the compiler complains thatinner
is notClone
. But again, with functions not quite being first class types, I'm having a bit of an issue resolving that types I actually have. Do you have any hints for me? – gspr Commented Apr 1 at 11:06