現在、Rust で単純なパーサー コンビネーター ライブラリを実装しようとしています。map
そのために、パーサーの結果を変換する汎用関数が必要です。
問題は、クロージャーを保持する構造体をコピーする方法がわからないことです。例はMap
、次の例の構造体です。mapFunction
前のパーサーの結果を受け取り、新しい結果を返す関数を格納するフィールドがあります。Map
それ自体がパーサーであり、他のパーサーとさらに組み合わせることができます。
ただし、パーサーを組み合わせるには、それらをコピー可能にする (Clone
特性をバインドする) 必要がありますが、これをどのように提供すればよいMap
でしょうか?
例: (疑似コードのみ、コンパイルされない可能性が高い)
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'));
}