2017-05-28 64 views
-1

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

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 *流as mutable more than once at a time。阅读其他stackoverflow问题只回答为什么发生这个问题,但不是如何解决问题。

回答

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() 
} 

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

+0

谢谢。将代码重构为单一匹配。 –