zero or more
This commit is contained in:
parent
4eda356fd7
commit
870c9beb54
37
src/lib.rs
37
src/lib.rs
@ -1,5 +1,6 @@
|
||||
#![feature(assert_matches)]
|
||||
#![allow(dead_code)] //TODO eventually turn this off
|
||||
use std::rc::Rc;
|
||||
|
||||
type ParseResult<I, O, E> = Result<(O, I), E>;
|
||||
|
||||
@ -16,6 +17,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, O, E, T> Parser<I, O, E> for Rc<T>
|
||||
where
|
||||
T: Parser<I, O, E>,
|
||||
{
|
||||
fn parse(&self, input: I) -> ParseResult<I, O, E> {
|
||||
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<P, I, O>(parser: P) -> impl Parser<I, Vec<O>, I>
|
||||
fn zero_or_more<P, I, O>(parser: P) -> impl Parser<I, Vec<O>, I>
|
||||
where
|
||||
P: Parser<I, O, I>,
|
||||
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<P, I, O>(parser: P) -> impl Parser<I, Vec<O>, I>
|
||||
where
|
||||
P: Parser<I, O, I>,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user