我正在尝试在Rust中实现Monkey玩具语言。我现在正在尝试生成和AST,但是在此之前,我需要具有一个正常运行的解析器。我已经有了我的词法分析器。
所以解析器的相关部分如下:
struct Parser<'a> {
lexer: lexer::Lexer<'a>,
current_token: Token<'a>,
peek_token: Token<'a>,
}
impl<'a> Parser<'a> {
// Create a new parser.
// Depends on a lexer capable of iterating over
// the tokens.
pub fn new(mut lexer: lexer::Lexer<'a>) -> Parser {
// constructor
}
// Read the next token.
//
// Returns self to avoid weird `move out of
// borrowed content` issue?
fn next_token(mut self) -> Self {
self.current_token = self.peek_token;
self.peek_token = self.lexer.next_token();
self
}
}
问题出在next_token
函数中。我真的希望它可以与借来的&self
一起使用,就像这样:
// Read the next token.
fn next_token(&mut self) {
self.current_token = self.peek_token;
self.peek_token = self.lexer.next_token();
}
但是编译器抱怨移出借来的内容。现在,我了解为什么发生了 :我只是借用self
,不能执行从self.peek_token
到self.current_token
的移动,因为我不拥有它
我的问题是,返回Self
是最好的策略吗?返回Self
的代码可以正常工作,但是界面变得非常难看。
#[test]
fn test_next_token() {
let l = lexer::Lexer::new("let answer = 42;");
let p = Parser::new(l);
assert_eq!(p.current_token, Token::Let);
let p = p.next_token();
assert_eq!(p.current_token, Token::Ident("answer"));
}
我没有其他选择吗?这是Rust中常见的习惯用法吗?
这里是指向playground的链接。
答案 0 :(得分:3)
您可以使用std::mem::replace
:
use std::mem;
// Read the next token.
fn next_token(&mut self) {
self.current_token = mem::replace(&mut self.peek_token, self.lexer.next_token());
}
replace
将第二个参数存储到第一个参数中,并返回第一个参数的当前值,然后将其分配给current_token
。