gpt4 book ai didi

rust - 共享生命周期的力场

转载 作者:行者123 更新时间:2023-11-29 08:17:11 25 4
gpt4 key购买 nike

我使用的是 Rust 0.13,对 Rust 还是个新手。我有一个想要拥有字符串 input 的结构,但我有想要使用该字符串的切片的代码,work

pub struct Lexer<'a> {
input : Option<String>,
work : &'a str,
...
}

我的目标是将一个字符串传递给该结构,让它创建自己的副本,然后创建一个指向该字符串的初始切片。理想情况下,我现在可以使用这个切片来操作它,因为支持切片的内存永远不会改变。

pub fn input(&mut self, input : String) {
self.input = Some(input.clone());
self.work = self.input.unwrap().as_slice();
}

impl<'lex> Iterator<Token> for Lexer<'lex> {
fn next(&mut self) -> Option<Token> {
// ...Do work...
match regex!("\\S").find(self.work) {
Some((0, end)) => {
// Cheap to move the view around
self.work = self.work.slice_from(end);
},
_ => ()
}
// ... Do more work ...
}
}

但是,这不起作用,因为生命周期太短了:

error: borrowed value does not live long enough
self.work = self.input.unwrap().as_slice();
^~~~~~~~~~~~~~~~~~~

我将其解释为 self.input 可以更改,从而使 self.work 的 View 无效。这是一个合理的解释吗?

有没有办法指定这些字段以某种方式相互关联?我认为如果我可以指定 Lexer.input 是最终的,这会起作用,但看起来 Rust 没有办法做到这一点。

编辑:示例调用代码

let mut lexer = lex::Lexer::new();

lexer.add("[0-9]+", Token::NUM);
lexer.add("\\+", Token::PLUS);

for line in io::stdin().lock().lines() {
match line {
Ok(input) => {
lexer.input(input.as_slice());
lexer.lex();
},
Err(e) => ()
}
}

最佳答案

我认为你的问题可以通过增加一层来解决。你可以有一个层来收集你的词法分析器的规则,然后你创建一个新的结构来实际执行词法分析。这与 Rust 中的迭代器是如何自己实现的是平行的!

struct MetaLexer<'a> {
rules: Vec<(&'a str, u32)>,
}

impl<'a> MetaLexer<'a> {
fn new() -> MetaLexer<'a> { MetaLexer { rules: Vec::new() } }

fn add_rule(&mut self, name: &'a str, val: u32) {
self.rules.push((name, val));
}

fn lex<'r, 's>(&'r self, s: &'s str) -> Lexer<'a, 's, 'r> {
Lexer {
rules: &self.rules,
work: s,
}
}
}

struct Lexer<'a : 'r, 's, 'r> {
rules: &'r [(&'a str, u32)],
work: &'s str,
}

impl<'a, 's, 'r> Iterator for Lexer<'a, 's, 'r> {
type Item = u32;

fn next(&mut self) -> Option<u32> {
for &(name, val) in self.rules.iter() {
if self.work.starts_with(name) {
self.work = &self.work[name.len()..];
return Some(val);
}
}

None
}
}

fn main() {
let mut ml = MetaLexer::new();
ml.add_rule("hello", 10);
ml.add_rule("world", 3);

for input in ["hello", "world", "helloworld"].iter() {
// So that we have an allocated string,
// like io::stdin().lock().lines() might give us
let input = input.to_string();

println!("Input: '{}'", input);
for token in ml.lex(&input) {
println!("Token was: {}", token);
}
}
}

真的,你可以重命名 MetaLexer -> LexerLexer -> LexerItems,然后你' d 真正匹配标准库中的迭代器。

如果您的问题是真的我如何保留对从 stdin 读取的数据的引用,那是一个不同的问题,并且与您的原始陈述相去甚远。

关于rust - 共享生命周期的力场,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27694413/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com