summaryrefslogtreecommitdiff
path: root/melib/src/parsec.rs
diff options
context:
space:
mode:
Diffstat (limited to 'melib/src/parsec.rs')
-rw-r--r--melib/src/parsec.rs79
1 files changed, 77 insertions, 2 deletions
diff --git a/melib/src/parsec.rs b/melib/src/parsec.rs
index 8eebf608..c4205b19 100644
--- a/melib/src/parsec.rs
+++ b/melib/src/parsec.rs
@@ -267,6 +267,76 @@ where
}
}
+pub fn pairmutation<'a, P1, P2, R1, R2>(parser1: P1, parser2: P2) -> impl Parser<'a, (R1, R2)>
+where
+ P1: Parser<'a, R1>,
+ P2: Parser<'a, R2>,
+{
+ move |input| {
+ if let ok @ Ok(_) = parser1.parse(input).and_then(|(next_input, result1)| {
+ parser2
+ .parse(next_input)
+ .map(|(last_input, result2)| (last_input, (result1, result2)))
+ }) {
+ return ok;
+ }
+ parser2.parse(input).and_then(|(next_input, result1)| {
+ parser1
+ .parse(next_input)
+ .map(|(last_input, result2)| (last_input, (result2, result1)))
+ })
+ }
+}
+
+#[macro_export]
+macro_rules! permutation {
+ ($input:expr, $($field:tt, $t:ty, $parser:expr),*) => {{
+ 'perm: {
+ struct PermStruct {
+ $($field: Option<$t>),*
+ }
+ let mut results = PermStruct {
+ $($field: None),*
+ };
+ let mut input = $input;
+ let mut left = 0;
+ $(_ = &$parser; left += 1;)*
+ let mut count = 1;
+ let mut finished = 0;
+ loop {
+ let mut any_success = false;
+ $(if results.$field.is_none() {
+ if let Ok((rest, res)) = $parser.parse(input) {
+ if !matches!(res, None) || count > left {
+ results.$field = Some(res);
+ finished += 1;
+ count = 1;
+ input = rest;
+ }
+ any_success = true;
+ }
+ })*
+ count += 1;
+
+ if !any_success {
+ break 'perm Err(input);
+ }
+ if finished == left || count >= 2*left {
+ break;
+ }
+
+ }
+ if finished != left {
+ break 'perm Err(input);
+ }
+ let PermStruct {
+ $($field),*
+ } = results;
+ Ok((input, ($($field.unwrap()),*)))
+ }
+ }}
+}
+
pub fn prefix<'a, PN, P, R, RN>(pre: PN, parser: P) -> impl Parser<'a, R>
where
PN: Parser<'a, RN>,
@@ -293,9 +363,14 @@ where
}
}
-pub fn delimited<'a, PN, RN, P, R>(lparser: PN, mid: P, rparser: PN) -> impl Parser<'a, R>
+pub fn delimited<'a, PNL, PNR, LN, RN, P, R>(
+ lparser: PNL,
+ mid: P,
+ rparser: PNR,
+) -> impl Parser<'a, R>
where
- PN: Parser<'a, RN>,
+ PNL: Parser<'a, LN>,
+ PNR: Parser<'a, RN>,
P: Parser<'a, R>,
{
move |input| {