Capture the entire contiguous matched input with n

2019-02-18 01:47发布

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).

1条回答
一夜七次
2楼-- · 2019-02-18 02:34

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"aaabcccffffd"), IResult::Done(&b"ffffd"[..], "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.

查看更多
登录 后发表回答