I'm currently trying to implement a simple Parser-Combinator library in Rust. For that I would like to have a generic map
function to transform the result of a parser.
The problem is that I don't know how to copy a struct holding a closure. An example is the Map
struct in the following example. It has a mapFunction
field storing a function, which receives the result of the previous parser and returns a new result. Map
is itself a parser that can be further combined with other parsers.
However, for parsers to be combined I would need them to be copyable (having the Clone
trait bound), but how do I provide this for Map
?
Example: (Only pseudocode, will most likely not compile)
trait Parser<A> { // Cannot have the ": Clone" bound because of `Map`.
// Every parser needs to have a `run` function that takes the input as argument
// and optionally produces a result and the remaining input.
fn run(&self, input: ~str) -> Option<(A, ~str)>
}
struct Char {
chr: char
}
impl Parser<char> for Char {
// The char parser returns Some(char) if the first
fn run(&self, input: ~str) -> Option<(char, ~str)> {
if input.len() > 0 && input[0] == self.chr {
Some((self.chr, input.slice(1, input.len())))
} else {
None
}
}
}
struct Map<'a, A, B, PA> {
parser: PA,
mapFunction: 'a |result: A| -> B,
}
impl<'a, A, B, PA: Parser<A>> Parser<B> for Map<'a, A, B, PA> {
fn run(&self, input: ~str) -> Option<(B, ~str)> {
...
}
}
fn main() {
let parser = Char{ chr: 'a' };
let result = parser.run(~"abc");
// let mapParser = parser.map(|c: char| atoi(c));
assert!(result == Some('a'));
}
It's possible if you take a reference to the closure because you can
Copy
references.Cloning closures is not possible in general. However, you can make a struct type that contains the variables that the function uses, derive
Clone
on it, and then implementFn
on it yourself.Example of a reference to a closure: