2016-12-27 60 views
0

我想重寫我的解析器,以允許字符串傳遞到解析方法,而不是被綁定到結構。生鏽的解析器結構在鏽

以前,我的代碼是這樣的:

use std::collections::HashMap; 
use std::str; 

#[derive(Debug)] 
pub enum ParserError { 
    Generic 
} 

pub struct Resource(
    pub HashMap<String, String> 
); 

pub struct Parser<'a> { 
    source: str::Chars<'a> 
} 

impl<'a> Parser<'a> { 
    pub fn new(source: &str) -> Parser { 
     Parser { source: source.chars() } 
    } 
    pub fn parse(&mut self) -> Result<Resource, ParserError> { 
     let entries = HashMap::new(); 
     Ok(Resource(entries)) 
    } 
} 

fn main() { 
    let parser = Parser::new("key1 = Value 1"); 
    let res = parser.parse(); 
} 

,並在我的新代碼,我想是這樣的:

use std::collections::HashMap; 
use std::str; 

#[derive(Debug)] 
pub enum ParserError { 
    Generic 
} 

pub struct Resource(
    pub HashMap<String, String> 
); 

pub struct Parser<'a> { 
    source: Option<str::Chars<'a>> 
} 

impl<'a> Parser<'a> { 
    pub fn new() -> Parser<'a> { 
     Parser { source: None } 
    } 
    pub fn parse(&mut self, source: &str) -> Result<Resource, ParserError> { 
     self.source = Some(source.chars()); 

     let entries = HashMap::new(); 
     Ok(Resource(entries)) 
    } 
} 

fn main() { 
    let parser = Parser::new(); 
    parser.parse("key1 = Value 1"); 
    parser.parse("key2 = Value 2"); 
} 

,但好像我在有生之年搞亂一種我不完全適應的方式。我得到的錯誤是:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements 
    --> test.rs:22:35 
    | 
22 |   self.source = Some(source.chars()); 
    |  

處理這個問題的規範方法是什麼?我如何獲取String並將其克隆到Parser結構的生存期中?

回答

1

完整的錯誤信息是:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements 
    --> src/main.rs:22:35 
    | 
22 |   self.source = Some(source.chars()); 
    |         ^^^^^ 
    | 
help: consider using an explicit lifetime parameter as shown: fn parse(&mut self, source: &'a str) -> Result<Resource, ParserError> 
    --> src/main.rs:21:5 
    | 
21 |  pub fn parse(&mut self, source: &str) -> Result<Resource, ParserError> { 
    | ^

否則因爲它表明:

pub fn parse(&mut self, source: &'a str) -> Result<Resource, ParserError> 

允許代碼編譯和運行(在main固定無關錯配可變性後)。


要了解區別,您必須先了解lifetime elision

你原來的代碼是:

fn new(source: &str) -> Parser // with elision 
fn new<'b>(source: &'b str) -> Parser<'b> // without elision 

在口頭上,一般壽命參數結構的'a被捆綁到輸入字符串的壽命。

你的新代碼更復雜:

fn new() -> Parser<'b> 

// with elision 
fn parse(&mut self, source: &str) -> Result<Resource, ParserError> 
// without elision 
fn parse<'c, 'd>(&'c mut self, source: &'d str) -> Result<Resource, ParserError> 

在口頭上,一般壽命參數struct的'a仍由的new調用者定義的,但現在它不依賴於從構造函數什麼。當調用parse時,您試圖傳遞一個不相關生命期的字符串並存儲對它的引用(通過Chars迭代器)。由於兩個生命週期不相關,所以你不能確定它會持續多久。