fml 0.6.8

Friendly Markup Language
Documentation
use super::*;

macro_rules! esc_identity {
    ($esc:expr) => {{
        use winnow::{ascii::*, combinator::*, prelude::*, token::*};
        preceded('\\', $esc.take())
    }};
    ($first:expr, $($more:expr),+) => {{
        use winnow::{ascii::*, combinator::*, prelude::*, token::*};
        preceded('\\', alt(($first, $($more),+)).take())
    }};
}
pub(super) use esc_identity;

/// Line-long-pattern, must be called at start-of-line.\
/// Will gather non-blank text from consecutive lines starting with `pattern` followed by `space1`.\
/// The returned String contains separating newlines but does not contain the leading `pattern`.
/// ```ignore
/// llp!(pattern)
/// ```  
macro_rules! llp {
    ($pattern:expr) => {{
        use winnow::{ascii::*, combinator::*, prelude::*, token::*};

        repeat(
            1..,
            delimited(
                ($pattern, space1),
                slice_till!(1.., not!(line_ending, eof)).verify(|s: &str| !s.trim().is_empty()),
                alt((line_ending, eof)),
            ),
        )
        .fold(String::new, |mut acc, s| {
            if !acc.is_empty() {
                acc.push_str(LINE_ENDING);
            }
            acc.push_str(s);
            acc
        })
    }};
}
pub(super) use llp;

/// Repeats body until terminating parser found (or body fails),
/// does not accumulate and outputs taken input.
/// ```ignore
/// slice_till!(1.., body, terminating)
/// slice_till!(1.., body)
/// ```
macro_rules! slice_till {
    ($occur:expr, $body:expr, $term:expr) => {{
        use winnow::{ascii::*, combinator::*, prelude::*, token::*};

        repeat_till($occur, $body, $term).map(|((), _)| ()).take()
    }};

    ($occur:expr, $body:expr) => {{
        use winnow::{ascii::*, combinator::*, prelude::*, token::*};

        repeat($occur, $body).map(|()| ()).take()
    }};
}
pub(super) use slice_till;

/// Takes `any` token once, after having checked for the expected failure of `parser`.\
/// ```ignore
/// not!(parser)
/// ```
macro_rules! not {
	($parser:expr) => {
		preceded(not($parser), any.take())
	};
	($x:expr, $($y:expr),+) => {
		// $($y),+
		// right parser will eval to `any` eventually
        not!(alt(($x.void(), $($y.void()),+)))
    }
}
pub(super) use not;

/// Takes `any` token repeatedly, after having checked for the expected failure of `parser`.\
/// Allows escaping of the terminating parser and the escape char itself: `\`
/// ```ignore
/// enot!(token)
/// enot!(parser, escaped_value)
/// ```
macro_rules! enot {
    ($token:expr) => {
        enot!($token, $token)
    };

    ($parser:expr, $value:expr) => {
        escaped(
            not!($parser, "\\"),
            '\\',
            alt(($parser.value($value), "\\".value("\\"), empty.value("\\"))),
        )
    };
}
pub(super) use enot;

/// Delimited escapable string.\
/// Takes delimiting tokens and returns a string delimited by them,
/// allowing for escaping both the terminating token and the escape char itself with `\`.
/// ```ignore
///	delimited_str_esc!(left, right)
/// delimited_str_esc!(delim)
/// ```
macro_rules! delimited_esc {
    ($delim:expr) => {
        delimited_esc!($delim, $delim)
    };
    ($left:expr, $right:expr) => {{
        use winnow::{
            ascii::*,
            combinator::*,
            error::{ParserError, StrContext},
            prelude::*,
            token::*,
        };
        use $crate::parser::functions::macros::*;
        delimited(
            $left,
            enot!($right).verify(|x: &String| !x.trim().is_empty()),
            $right,
        )
    }};
}
pub(super) use delimited_esc;

// NOTE: `repeat(occur, not!(parser))` can be used instead of this
// /// A call of `repeat_till` which accepts `any` tokens up until the terminator is found.\
// /// This shorthand is useful because in the original `repeat_till`, the terminator check
// /// is applied _after_ the actual parser, making it so that if `any` is used as the parser,
// /// it would accept the terminator token once before actually terminating.
// /// ```ignore
// /// while_not(occurances, ending)
// /// ```
// macro_rules! while_not {
// 	($occur:expr, $ending:expr) => {
// 		repeat_till($occur, not!($ending), $ending)
// 	};
// }