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)]
|
#![feature(assert_matches)]
|
||||||
#![allow(dead_code)] //TODO eventually turn this off
|
#![allow(dead_code)] //TODO eventually turn this off
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
type ParseResult<I, O, E> = Result<(O, I), E>;
|
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> {
|
fn literal(expected: &'static str) -> impl Fn(&str) -> ParseResult<&str, &str, &str> {
|
||||||
move |input| match input.get(0..expected.len()) {
|
move |input| match input.get(0..expected.len()) {
|
||||||
Some(next) if next == expected => Ok((expected, &input[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
|
where
|
||||||
P: Parser<I, O, I>,
|
P: Parser<I, O, I>,
|
||||||
I: Copy,
|
I: Copy,
|
||||||
@ -57,13 +67,6 @@ where
|
|||||||
move |mut input| {
|
move |mut input| {
|
||||||
let mut results = Vec::new();
|
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) {
|
while let Ok((item, rest)) = parser.parse(input) {
|
||||||
results.push(item);
|
results.push(item);
|
||||||
input = rest;
|
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
|
/// Parses a standard identifier in a programming language
|
||||||
fn identifier(input: &str) -> ParseResult<&str, String, &str> {
|
fn identifier(input: &str) -> ParseResult<&str, String, &str> {
|
||||||
let mut chars = input.chars();
|
let mut chars = input.chars();
|
||||||
@ -130,5 +149,7 @@ mod tests {
|
|||||||
let p = one_or_more(literal("bongo "));
|
let p = one_or_more(literal("bongo "));
|
||||||
let input = "bongo bongo bongo bongo bongo ";
|
let input = "bongo bongo bongo bongo bongo ";
|
||||||
assert_matches!(p.parse(input), Ok((v, "")) if v.len() == 5);
|
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