我正在Rust中实现一个基本的代码解析器。我想对语言的标记进行迭代。我的自定义迭代器结构将借用存储在另一个结构中的代码String
。这是实现:
fn main() {
let tokenizer = Tokenizer {
code: String::from("foo + bar "),
};
let token_iter = tokenizer.tokens();
let program = parse(Box::new(token_iter));
println!("{:?}", program);
}
#[derive(Debug)]
enum Token {
Symbol(&'static str),
Identifier(String),
}
struct Tokenizer {
code: String,
}
impl Tokenizer {
fn tokens(&self) -> TokenIterator {
TokenIterator::new(&self.code)
}
}
struct TokenIterator<'a> {
code: &'a str,
}
impl<'a> TokenIterator<'a> {
fn new(code: &'a str) -> TokenIterator {
TokenIterator { code: code.trim() }
}
}
impl<'a> Iterator for TokenIterator<'a> {
type Item = Token;
fn next(&mut self) -> Option<Self::Item> {
if self.code.len() == 0 {
return None;
}
if self.code.starts_with("+") {
self.code = &self.code[1..].trim_left();
return Some(Token::Symbol("+"));
}
let first_char = self.code.chars().nth(0).unwrap();
if first_char.is_alphabetic() || first_char == '_' {
let mut ident = String::new();
while self.code.chars().nth(0).unwrap().is_alphanumeric()
|| self.code.chars().nth(0).unwrap() == '_'
{
ident.push(self.code.chars().nth(0).unwrap());
self.code = &self.code[1..];
}
self.code = self.code.trim_left();
return Some(Token::Identifier(ident));
}
panic!("invalid syntax:\n{}", self.code)
}
}
#[derive(Debug)]
struct Program {
name: &'static str,
tokens: Vec<Token>,
}
fn parse(tokens: Box<Iterator<Item = Token>>) -> Program {
Program {
tokens: tokens.collect(),
name: "foo",
}
}
编译器不允许我创建迭代器并将其绑定到变量。
error[E0597]: `tokenizer` does not live long enough
--> src/main.rs:5:26
|
5 | let token_iter = tokenizer.tokens();
| ^^^^^^^^^ borrowed value does not live long enough
...
8 | }
| - borrowed value only lives until here
|
= note: borrowed value must be valid for the static lifetime...
为什么令牌生成器需要在'static
生存期内生存?当我更改main
函数以在循环中使用迭代器而不将其绑定到局部变量时,它将如何编译?这段代码出于某些原因起作用...
fn main() {
let tokenizer = Tokenizer {
code: String::from("foo + bar "),
};
for token in tokenizer.tokens() {
println!("{:?}", token);
}
}