Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capture the entire contiguous matched input with nom

I'm looking to apply a series of nom parsers and return the complete &str that matches. I want to match strings of the form a+bc+. Using the existing chain! macro I can get pretty close:

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

where

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

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

Say we have 'aaabccc' as input. The above parser will match the input but only 'aaa' will be returned. What I would like to do is return 'aaabccc', the original input.

chain! is not the right macro for this, but there was not another that seemed more correct. What would the best way to do this be?


At the time of this writing I'm using nom 1.2.2 and rustc 1.9.0-nightly (a1e29daf1 2016-03-25).

like image 997
troutwine Avatar asked Mar 30 '16 05:03

troutwine


1 Answers

It appears as if you want recognized!:

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

And an example:

#[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,
    }
}

I'm not sure if chain! is the best way of combining sequential parsers if you don't care for the values, but it works in this case.

like image 189
Shepmaster Avatar answered Nov 15 '22 20:11

Shepmaster