我试图通过写一个简单的词法分析器来学习Rust。这是我到目前为止所拥有的......
use std::fs::File;
use std::io::Read;
use std::str::Chars;
pub struct Lexer<'a> {
file_name: String,
file_contents: String,
iterator: Option<Chars<'a>>,
}
impl<'a> Lexer<'a> {
fn new(fname: &str) -> Lexer {
Lexer {
file_name: fname.to_string(),
file_contents: String::new(),
iterator: None,
}
}
// Reads the file contents and creates iterator
fn init(&'a mut self) {
// Open the file
let mut f = File::open(&self.file_name).expect("Couldn't open file");
// Read the contents
f.read_to_string(&mut self.file_contents).expect("Couldn't read file contents");
self.iterator = Some(self.file_contents.chars());
}
// Gets the next character
fn get_next(&mut self) -> Option<char> {
self.iterator.unwrap().next()
}
}
fn main() {
let mut lexer = Lexer::new("test.txt");
lexer.init();
// Assuming the file "text.txt" contains "Hello World"
// then the following two lines should print "H" then "e"
println!("{}", lexer.get_next().unwrap());
println!("{}", lexer.get_next().unwrap());
}
但是当我尝试编译它时,我得到以下两个错误:
cannot move out of borrowed content [E0507]
main.rs:38 self.iterator.unwrap().next()
和
cannot borrow `lexer` as mutable more than once at a time [E0499]
main.rs:49 println!("{}", lexer.get_next().unwrap());
Google的第一个错误显示Clone()
- ing是这种错误的可能解决方案,但我相信在这种情况下这不会起作用,因为迭代器状态需要每次都更新next()
被称为。{/ p>
有没有人对如何克服这些问题并将其编译进行任何建议?
答案 0 :(得分:2)
最终,你正试图store a value and a reference to that value in the same struct。与其他配方不同,这个特定的案例允许您“引用”引用的结,但可能不会做您想要的。例如,在致电init
后,您永远无法移动Lexer
,因为移动它会使参考无效。
它还解释了“再次借用”错误。因为生命周期适用于self,并且它是一个可变引用,lexer本身将永远保留可变引用,这意味着没有其他任何东西可以改变它,包括它自己。
简短的回答是:不要那样组织你的代码。无论出于何种原因,解析和lexing是Rust社区中的一个流行问题。看看其他图书馆是如何做到的。
或者查看迭代器的工作原理。迭代的项目保持不变,并返回一个引用原始项目的单独迭代器。
将您的代码拆分为相同的两个部分可能是最好的方向。