【问题标题】:Refactor parser code to avoid borrow checker issue重构解析器代码以避免借用检查器问题
【发布时间】:2017-05-28 19:46:47
【问题描述】:

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

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*streamas mutable more than once at a time 的编译器投诉。阅读其他stackoverflow问题只回答了为什么会出现这个问题,而不是如何解决这个问题。

【问题讨论】:

    标签: rust borrow-checker


    【解决方案1】:

    您的peek函数不需要&amp;mut self,而仅使用&amp;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")),
        }
    }
    

    或者您可以将 peek 更改为

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

    这不会造成借用问题,但会克隆数据。

    【讨论】:

    • 谢谢。将代码重构为只有一个匹配有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-28
    • 1970-01-01
    • 2019-09-28
    • 1970-01-01
    • 1970-01-01
    • 2015-12-15
    相关资源
    最近更新 更多