Sequence trait

This commit is contained in:
Greg Shuflin 2024-01-26 09:39:46 -08:00
parent 477fc50b65
commit e697b8ed21
2 changed files with 30 additions and 10 deletions

View File

@ -39,7 +39,7 @@ mod tests {
#[test] #[test]
fn test_sequence() { fn test_sequence() {
let parser = sequence(literal("bongo"), sequence(literal(" "), literal("jonzzz"))); let parser = seq2(literal("bongo"), seq2(literal(" "), literal("jonzzz")));
let output = parser.parse("bongo jonzzz").unwrap(); let output = parser.parse("bongo jonzzz").unwrap();
assert_eq!(output.0 .0, "bongo"); assert_eq!(output.0 .0, "bongo");
assert_eq!(output.0 .1, (" ", "jonzzz")); assert_eq!(output.0 .1, (" ", "jonzzz"));
@ -61,7 +61,7 @@ mod tests {
#[test] #[test]
fn test_map() { fn test_map() {
let parser = map( let parser = map(
sequence(literal("a"), literal("b")), seq2(literal("a"), literal("b")),
|(_a, _b): (&str, &str)| 59, |(_a, _b): (&str, &str)| 59,
); );
let output = parser.parse("abcd").unwrap(); let output = parser.parse("abcd").unwrap();
@ -70,16 +70,16 @@ mod tests {
#[test] #[test]
fn test_combinators() { fn test_combinators() {
let parser = sequence(map(repeated(literal_char('a')), |_| 10), literal_char('b')); let parser = seq2(map(repeated(literal_char('a')), |_| 10), literal_char('b'));
let output = parser.parse("aaaaaaaabcd").unwrap(); let output = parser.parse("aaaaaaaabcd").unwrap();
assert_eq! {((10, 'b'), "cd"), output}; assert_eq! {((10, 'b'), "cd"), output};
} }
#[test] #[test]
fn test_optional() { fn test_optional() {
let parser = sequence( let parser = seq2(
optional(literal("alpha")), optional(literal("alpha")),
sequence(repeated(literal(" ")), literal("beta")), seq2(repeated(literal(" ")), literal("beta")),
); );
let output1 = parser.parse(" beta").unwrap(); let output1 = parser.parse(" beta").unwrap();

View File

@ -1,13 +1,33 @@
use crate::{ParseResult, Parser}; use crate::{ParseResult, Parser};
pub fn sequence<I, O1, O2, E>( pub fn sequence<S, I, O, E>(sequence: S) -> impl Parser<I, O, E>
where
S: Sequence<I, O, E>,
{
move |input| -> ParseResult<I, O, E> { sequence.parse(input) }
}
pub fn seq2<I, O1, O2, E>(
first: impl Parser<I, O1, E>, first: impl Parser<I, O1, E>,
second: impl Parser<I, O2, E>, second: impl Parser<I, O2, E>,
) -> impl Parser<I, (O1, O2), E> { ) -> impl Parser<I, (O1, O2), E> {
move |input| -> ParseResult<I, (O1, O2), E> { sequence((first, second))
first.parse(input).and_then(|(result1, rest)| { }
second
.parse(rest) pub trait Sequence<I, O, E> {
fn parse(&self, input: I) -> ParseResult<I, O, E>;
}
impl<P1, P2, I, O1, O2, E> Sequence<I, (O1, O2), E> for (P1, P2)
where
P1: Parser<I, O1, E>,
P2: Parser<I, O2, E>,
{
fn parse(&self, input: I) -> ParseResult<I, (O1, O2), E> {
let p1 = &self.0;
let p2 = &self.1;
p1.parse(input).and_then(|(result1, rest)| {
p2.parse(rest)
.map(|(result2, rest2)| ((result1, result2), rest2)) .map(|(result2, rest2)| ((result1, result2), rest2))
}) })
} }