2016-03-30 13 views
4

Ich bin auf der Suche nach einer Reihe von nom Parsern und geben Sie die komplette &str, die übereinstimmt. Ich möchte Zeichenfolgen des Formulars a+bc+ übereinstimmen. Mit dem bestehenden chain! macro kann ich ziemlich nahe kommen:Capture den gesamten zusammenhängenden Eingang mit nom

named!(aaabccc <&[u8], &str>, 
    map_res!(
     chain!(
      a: take_while!(is_a) ~ 
       tag!("b") ~ 
       take_while!(is_c) , 
      || {a} 
      ), 
     from_utf8 
    )); 

wo

fn is_a(l: u8) -> bool { 
    match l { 
     b'a' => true, 
     _ => false, 
    } 
} 

fn is_c(l: u8) -> bool { 
    match l { 
     b'c' => true, 
     _ => false, 
    } 
} 

Sagen wir 'aaabccc' als Eingang. Der obige Parser passt die Eingabe an, aber nur 'aaa' wird zurückgegeben. Was ich tun möchte, ist "aaabccc", die ursprüngliche Eingabe, zurückzugeben.

chain! ist nicht das richtige Makro dafür, aber es gab kein anderes, das richtiger schien. Was wäre der beste Weg dies zu tun?


Zum Zeitpunkt des Schreibens dieses Artikels ich nom bin mit 1.2.2 und rustc 1.9.0-nightly (a1e29daf1 2016-03-25).

Antwort

3

Es scheint, als ob Sie recognized! wollen:

if the child parser was successful, return the consumed input as produced value

Und ein Beispiel:

#[macro_use] 
extern crate nom; 

use nom::IResult; 

fn main() { 
    assert_eq!(aaabccc(b"aaabcccddd"), IResult::Done(&b"ddd"[..], "aaabccc")); 
} 

named!(aaabccc <&[u8], &str>, 
    map_res!(
     recognize!(
      chain!(
       take_while!(is_a) ~ 
       tag!("b") ~ 
       take_while!(is_c), 
       || {} 
      ) 
     ), 
     std::str::from_utf8 
    ) 
); 

fn is_a(l: u8) -> bool { 
    match l { 
     b'a' => true, 
     _ => false, 
    } 
} 

fn is_c(l: u8) -> bool { 
    match l { 
     b'c' => true, 
     _ => false, 
    } 
} 

Ich bin nicht sicher, ob chain! die beste Art und Weise zu kombinieren sequentielle Parser ist, wenn Sie nicht tun Sorge für die Werte, aber es funktioniert in diesem Fall.

+0

Ah, ich hatte "erkenne!" Missverstanden. Vielen Dank! – troutwine

+0

Was ist, wenn ich '<&str, &str>' habe, nicht '<&[u8], &str>'? Ich bekomme 'Fehler: keine Methode namens \ 'offset \' gefunden für Typ \ '& str \' im aktuellen Bereich' – Sergey