2017-05-28 3 views
-1

Was ist der beste Weg, um diesen Parser-Code zu refaktorieren, um Border Checker Problem zu vermeiden?Refactor Parser-Code, um zu vermeiden, Border Checker Problem

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

Der Compiler Beschwerde über cannot borrow * stream as mutable more than once at a time. Beim Lesen anderer stackoverflow-Fragen wurde nur geklärt, warum dieses Problem aufgetreten ist, aber nicht, wie das Problem zu lösen ist.

Antwort

1

Ihre peek Funktion muss kein &mut self, und mit nur ein &self wäre völlig Ihre Fehler beheben und Sie cannot borrow *stream as mutable because it is also borrowed as immutable geben. Wie auch immer, das Vermeiden von mut, wenn nicht benötigt, ist besser.

Ihr Problem ist, dass Sie diese Token Referenz an t binden, damit das Borgen nicht endet. Sie brauchen nicht ein Multi-Level-match haben und kann mit

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")), 
    } 
} 

das gleiche tun Oder Sie könnten peek auf

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

, die keine borrow Problem schaffen würde sich ändern, aber klonen die Daten.

+0

danke. Refactoring den Code auf nur einzelne Übereinstimmung geholfen. –

Verwandte Themen