Skip to content

Instantly share code, notes, and snippets.

@ArtemGr
Last active August 24, 2016 23:26
Show Gist options
  • Save ArtemGr/63a5957fb8b342e097f100d857e3dbf6 to your computer and use it in GitHub Desktop.
Save ArtemGr/63a5957fb8b342e097f100d857e3dbf6 to your computer and use it in GitHub Desktop.
Nom tag that implements the /(?x) (.*?) (remainder)/ pattern.
/// Implements the /(?x) (.*?) (remainder)/ pattern:
/// looks for remainder first, then returns a tuple with the prefix and the remainder.
/// Discussion: https://www.reddit.com/r/rust/comments/4yokxd/crash_course_into_nom_kind_of_question/
macro_rules! take_until_parse_s (
($i: expr, $submac: ident! ($($args:tt)*)) => ({
let input = $i as &str;
let mut ret = IResult::Error (nom::Err::Position (nom::ErrorKind::Custom (0), input));
for (pos, _) in $i.char_indices() {
match $submac! (&input[pos..], $($args)*) {
IResult::Done (i,o) => {ret = IResult::Done (i, (&input[0..pos], o)); break}, // Found the remainder!
IResult::Error(_) => continue, // Keep looking.
IResult::Incomplete(_) => continue}} // Keep looking.
if !ret.is_done() {
// Last chance. See if subparser accepts an empty string.
if let IResult::Done (i,o) = $submac! ("", $($args)*) {
ret = IResult::Done (i, (input, o))}} // Empty remainder was accepted.
ret});
($i: expr, $f: expr) => (take_until_parse_s! ($i, call! ($f));););
/// `$starts` is an optional `Pattern` used to optimize the `$submac` search.
/// For example, with jetscii: `take_until_find_parse_s! ("foo bar", ascii_chars! ('b'), tag_s! ("bar"))`.
macro_rules! take_until_find_parse_s (
($i: expr, $starts: expr, $submac: ident! ($($args:tt)*)) => ({
let input = $i as &str;
let mut ret = IResult::Error (nom::Err::Position (nom::ErrorKind::Custom (0), input));
for (pos, _) in $i.match_indices ($starts) {
match $submac! (&input[pos..], $($args)*) {
IResult::Done (i,o) => {ret = IResult::Done (i, (&input[0..pos], o)); break}, // Found the remainder!
IResult::Error(_) => continue, // Keep looking.
IResult::Incomplete(_) => continue}} // Keep looking.
ret});
($i: expr, $starts: expr, $f: expr) => (take_until_find_parse_s! ($i, $starts, call! ($f));););
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment