2015-04-28 54 views
1

我試圖使用Rust中的parser_combinators庫來解析一個字符串。我想要解析的真實數據看起來是這樣的:使用解析器組合器來解析帶有轉義字符的字符串?

A79,216,0,4,2,2,N,"US\"PS" 

所以在那個數據到底是在引號的字符串,但該字符串將包含轉義字符爲好。我無法弄清楚如何解析其他引號之間的轉義字符。

extern crate parser_combinators; 

use self::parser_combinators::*; 

fn main() { 
    let s = r#""HE\"LLO""#; 
    let data = many(satisfy(|c| c != '"')); // Fails on escaped " obviously 
    let mut str_parser = between(satisfy(|c| c == '"'), satisfy(|c| c == '"'), data); 
    let result : Result<(String, &str), ParseError> = str_parser.parse(s); 
    match result { 
     Ok((value, _)) => println!("{:?}", value), 
     Err(err) => println!("{}", err), 
    } 
} 

//=> "HE\\" 

上面的代碼將成功地解析該字符串,但顯然無法在中間的轉義字符,最終打印出"HE\\"

我想更改上面的代碼,以便打印"HE\\\"LLO"

我該怎麼做?

+0

'「\」HE \\\「LLO \」「''可能會寫得更好'r#」「HE \」LLO「」#'。 –

+0

@ChrisMorgan啊,所以_that's_你怎麼做'相當於'',更新了這個例子 – Fredrik

+0

Rust使用C♯風格的原始字符串,允許'r「...」','r#「...」#','r ##「...」##'*&c。* –

回答

1

我有一個功能強大的JSON解析器,作爲解析這種轉義字符的解析器組合器的基準。我在下面包含了一個鏈接和一個稍微簡化的版本。

fn json_char(input: State<&str>) -> ParseResult<char, &str> { 
    let (c, input) = try!(satisfy(|c| c != '"').parse_state(input)); 
    let mut back_slash_char = satisfy(|c| "\"\\nrt".chars().find(|x| *x == c).is_some()).map(|c| { 
     match c { 
      '"' => '"', 
      '\\' => '\\', 
      'n' => '\n', 
      'r' => '\r', 
      't' => '\t', 
      c => c//Should never happen 
     } 
    }); 
    match c { 
     '\\' => input.combine(|input| back_slash_char.parse_state(input)), 
     _ => Ok((c, input)) 
    } 
} 

json_char

由於該解析器可佔用1首或2個字符是不夠用的原語組合子,所以我們需要引入其可以在其上被解析的字符分支的功能。