重构解析器代码以避免借用检查器问题

时间:2017-05-28 19:46:48

标签: rust borrow-checker

重构此解析器代码以避免借用检查程序问题的最佳方法是什么?

pub type Token=u8;
pub trait Stream {
    type Item;
    fn next(&mut self) -> Option<&Self::Item>;
    fn peek(&mut self) -> Option<&Self::Item>;
}

#[derive(Clone)]
pub struct Parser {
    input: Vec<Token>,
    position: usize,
}

pub type ParseError = String;
pub type ParseResult<T> = Result<T, ParseError>;

impl Stream for Parser {
    type Item = Token;

    fn next(&mut self) -> Option<&Token> {
        let token = self.input.get(self.position);
        self.position += 1;
        token
    }

    fn peek(&mut self) -> Option<&Token> {
        self.input.get(self.position + 1)
    }
}

fn parse_expr(stream: &mut Parser) -> ParseResult<()> {
    match stream.peek() { // ~~ borrowed stream here
        None => Err(String::from("No more tokens")),
        Some(t) => match t {
            &0 => parse_number_literal(stream), // ~~ and here
            &1 => panic!("parse string"),
            &2 => panic!("parse character"),
            _ => Err(String::from("Unexpected Token")),
        }
    }
}

fn parse_number_literal(stream: &mut Parser) -> ParseResult<()> {
    let token = stream.next();
    Ok(())
}

fn main(){}

关于cannot borrow * stream as mutable more than once at a time的编译器投诉。阅读其他stackoverflow问题只能解答为什么会出现这个问题而不是如何解决问题。

1 个答案:

答案 0 :(得分:1)

您的peek功能不需要&mut self,仅使用&self即可完全解决您的错误,并为您提供cannot borrow *stream as mutable because it is also borrowed as immutable。无论如何,在不需要时避免mut更好。

您的问题是您将Token引用绑定到t,因此借用不会结束。您不需要具有多级match,并且可以使用

执行相同的操作
fn parse_expr(stream: &mut Parser) -> ParseResult<()> {
    match stream.peek() {
        None => Err(String::from("No more tokens")),
        Some(&0) => parse_number_literal(stream),
        Some(&1) => panic!("parse string"),
        Some(&2) => panic!("parse character"),
        _ => Err(String::from("Unexpected Token")),
    }
}

或者你可以改为偷看

fn peek(&self) -> Option<Token> {
    self.input.get(self.position + 1).cloned()
}

不会产生借用问题,但会克隆数据。