From 870c9beb5439d9463672f6517a4966e1160b0949 Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Sun, 16 Oct 2022 00:30:06 -0700 Subject: [PATCH] zero or more --- src/lib.rs | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a08a7fa..8de4d8e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![feature(assert_matches)] #![allow(dead_code)] //TODO eventually turn this off +use std::rc::Rc; type ParseResult = Result<(O, I), E>; @@ -16,6 +17,15 @@ where } } +impl Parser for Rc +where + T: Parser, +{ + fn parse(&self, input: I) -> ParseResult { + self.as_ref().parse(input) + } +} + fn literal(expected: &'static str) -> impl Fn(&str) -> ParseResult<&str, &str, &str> { move |input| match input.get(0..expected.len()) { Some(next) if next == expected => Ok((expected, &input[expected.len()..])), @@ -49,7 +59,7 @@ where } } -fn one_or_more(parser: P) -> impl Parser, I> +fn zero_or_more(parser: P) -> impl Parser, I> where P: Parser, I: Copy, @@ -57,13 +67,6 @@ where move |mut input| { let mut results = Vec::new(); - if let Ok((result, rest)) = parser.parse(input) { - results.push(result); - input = rest; - } else { - return Err(input); - } - while let Ok((item, rest)) = parser.parse(input) { results.push(item); input = rest; @@ -73,6 +76,22 @@ where } } +fn one_or_more(parser: P) -> impl Parser, I> +where + P: Parser, + I: Copy, +{ + let parser = std::rc::Rc::new(parser); + map( + seq(parser.clone(), zero_or_more(parser)), + |(first, rest)| { + let mut output = vec![first]; + output.extend(rest.into_iter()); + output + }, + ) +} + /// Parses a standard identifier in a programming language fn identifier(input: &str) -> ParseResult<&str, String, &str> { let mut chars = input.chars(); @@ -130,5 +149,7 @@ mod tests { let p = one_or_more(literal("bongo ")); let input = "bongo bongo bongo bongo bongo "; assert_matches!(p.parse(input), Ok((v, "")) if v.len() == 5); + let input = "bongo ecks"; + assert_matches!(p.parse(input), Ok((v, "ecks")) if v.len() == 1); } }