我正在尝试用 Rust 编写一个优化的 Brainfuck 编译器。目前它将标记存储在一个平面向量中,这可以工作,但我无法将其更改为使用语法树:
#[derive(Clone, PartialEq, Eq)]
pub enum Token {
Output,
Input,
Loop(Vec<Token>),
Move(i32),
Add(i32, i32),
LoadOut(i32, i32),
}
use Token::*;
pub fn parse(code: &str) -> Vec<Token> {
let mut alltokens = Vec::new();
let mut tokens = &mut alltokens;
let mut tokvecs: Vec<&mut Vec<Token>> = Vec::new();
for i in code.chars() {
match i {
'+' => tokens.push(Add(0, 1)),
'-' => tokens.push(Add(0, -1)),
'>' => tokens.push(Move(1)),
'<' => tokens.push(Move(-1)),
'[' => {
tokens.push(Loop(Vec::new()));
tokvecs.push(&mut tokens);
if let &mut Loop(mut newtokens) = tokens.last_mut().unwrap() {
tokens = &mut newtokens;
}
},
']' => {
tokens = tokvecs.pop().unwrap();
},
',' => tokens.push(Input),
'.' => {
tokens.push(LoadOut(0, 0));
tokens.push(Output);
}
_ => (),
};
}
alltokens
}
我无法弄清楚如何处理[
命令。代码中的当前实现是我尝试过的几个之一,但都失败了。我认为它可能需要使用 Rust Box
,但我不太明白它是如何使用的。
处理命令的分支[
可能完全错误,但我不确定应该如何完成。它将包含向量Loop
的(枚举的变体)推送到向量。问题是然后在 that 中获得向量的可变借用,这是语句应该做的。Token
tokens
Loop
if let
该代码无法编译,因为newtokens
它没有超过块的末尾if let
。是否可以获得对内部向量的可变引用Loop
并设置tokens
为它?如果没有,可以做些什么呢?