Как передать один и тот же изменяемый Peekable различным функциям в Rust - PullRequest
1 голос
/ 28 января 2020

Я хочу написать парсер. Мне кажется практичным иметь изменяемый Iterator, который я могу передавать различным функциям синтаксического анализатора.

Я попытался проиллюстрировать упрощенный подход, который компилируется, но еще не идеален.

fn main() {
    let tokens = vec!["fIrSt".to_string(), "SeConD".to_string(), "tHiRd".to_string(), "FoUrTh".to_string()];

    let parsed = parse_input(tokens);

    println!("{}", parsed);
}

fn parse_input(tokens: Vec<String>) -> String {
    let mut tokens_iter = tokens.iter();

    let upps = parse_upper(&mut tokens_iter);
    let lowers = parse_lower(&mut tokens_iter);

    upps + &lowers
}

fn parse_upper(tokens_iter: &mut Iterator<Item=&String>) -> String {
    let mut result = String::new();
    let token_1 = tokens_iter.next().unwrap().to_uppercase();
    let token_2 = tokens_iter.next().unwrap().to_uppercase();
    result.push_str(&token_1);
    result.push_str(&token_2);
    result
}

fn parse_lower(tokens_iter: &mut Iterator<Item=&String>) -> String {
    let mut result = String::new();
    let token_1 = tokens_iter.next().unwrap().to_lowercase();
    let token_2 = tokens_iter.next().unwrap().to_lowercase();
    result.push_str(&token_1);
    result.push_str(&token_2);
    result
}

Как работает пример: Допустим, у меня есть некоторые данные, которые уже были токенизированы. Здесь он представлен вектором tokens (Vec<String>). Внутри внешней функции parse_input Vec преобразуется в Iterator, а затем передается в другие, специфические c функции синтаксического анализатора. Здесь: parse_upper и parse_lower. В реальной жизни это могут быть "parse_if_statement" или "parse_ while_l oop", но над какой частью работы Iterator работают, это не относится к вопросу. Важно то, что при каждом следующем вызове курсор перемещается на Iterator. Так что каждая функция потребляет части, которые ей нужны. Этот пример компилирует и выдает: FIRSTSECONDthirdfourth

Я хотел бы иметь возможность peek() в Iterator, прежде чем передать его функции. Это необходимо определить, какая функция должна быть вызвана. Но все, что я пробовал с использованием Peekable вместо Iterator, привело к полному времени жизни и заимствованию хаоса.

Любые предложения о том, как передать Peekable вместо Iterator в этом случае?

Возможно, использование Peekable в качестве параметра функции - плохая идея. Или, возможно, мой Iterator подход уже неверен. Все предложения / советы приветствуются.

...