Hi, I'm writing a parser library using combinators. There's a parser combinator (a function) called sequence
that takes many arguments so I extracted them into a struct that looks like this:
#[derive(Clone)]
struct SequenceArgs<'a, A: 'a, S: 'a> {
start: &'static str,
separator: &'static str,
end: &'static str,
spaces: BoxedParser<'a, (), S>,
item: BoxedParser<'a, A, S>,
trailing: Trailing,
}
#[derive(Clone)]
enum Trailing {
Forbidden,
Optional,
Mandatory,
}
In the sequence
function,
fn sequence<'a, A: Clone + 'a, S: Clone + 'a>(args: &'a SequenceArgs<'a, A, S>) -> BoxedParser<'a, Vec<A>, S>
I want to pass a reference called args
as argument. Only reference seems to work because closures inside the function required moving args
into them while the SequenceArgs
struct doesn't implement Copy
. The function definition worked but I struggled to find a way to create a static SequenceArgs
struct to call it.
let args = SequenceArgs {
start: "[",
end: "]",
separator: ",",
spaces: space0(),
item: token("abc"),
trailing: Trailing::Optional,
};
assert_eq!(
success(sequence(&args), "[ abc, abc, abc ]"), //!!!: &args doesn't live long enough
vec!["abc", "abc", "abc"]
)
The compiler complained that the borrowed value args
doesn't live long enough.
const
doesn't work because function calls like space0()
are not allowed.
static
doesn't work either because I used dynamic trait objects and Rc
which is not thread-safe.
So, how can I create a static struct and pass it as argument?
Link to relevant code in my repo.