use crate::parser::{ParseResult, Parser, ParserInput, Representation}; pub fn tuple2(parser1: P1, parser2: P2) -> impl Parser where I: ParserInput, P1: Parser, P2: Parser, { seq((parser1, parser2)) } pub fn seq(sequence: T) -> impl Parser where I: ParserInput, T: Sequence, { let rep = sequence.representation(); let p = move |input| sequence.parse(input); (p, rep) } /* TODO - eventually rewrite this parser combinator in Schala. Seeing what this * code that makes heavy use of type variables and abstraction over types looks like * in Schala's type system should be educational */ pub trait Sequence { fn parse(&self, input: I) -> ParseResult; fn representation(&self) -> Representation; } impl Sequence for (P1, P2) where I: ParserInput, P1: Parser, P2: Parser, { fn parse(&self, input: I) -> ParseResult { let parser1 = &self.0; let parser2 = &self.1; parser1.parse(input).and_then(|(result1, rest1)| { parser2 .parse(rest1) .map(|(result2, rest2)| ((result1, result2), rest2)) }) } fn representation(&self) -> Representation { let mut iter = [self.0.representation(), self.1.representation()].into_iter(); Representation::from_sequence(&mut iter) } } impl Sequence for (P1, P2, P3) where I: ParserInput, P1: Parser, P2: Parser, P3: Parser, { fn parse(&self, input: I) -> ParseResult { let parser1 = &self.0; let parser2 = &self.1; let parser3 = &self.2; let (result1, rest1) = parser1.parse(input)?; let (result2, rest2) = parser2.parse(rest1)?; let (result3, rest3) = parser3.parse(rest2)?; Ok(((result1, result2, result3), rest3)) } fn representation(&self) -> Representation { let mut iter = [ self.0.representation(), self.1.representation(), self.2.representation(), ] .into_iter(); Representation::from_sequence(&mut iter) } } impl Sequence for (P1, P2, P3, P4) where I: ParserInput, P1: Parser, P2: Parser, P3: Parser, P4: Parser, { fn parse(&self, input: I) -> ParseResult { let parser1 = &self.0; let parser2 = &self.1; let parser3 = &self.2; let parser4 = &self.3; let (result1, rest1) = parser1.parse(input)?; let (result2, rest2) = parser2.parse(rest1)?; let (result3, rest3) = parser3.parse(rest2)?; let (result4, rest4) = parser4.parse(rest3)?; Ok(((result1, result2, result3, result4), rest4)) } fn representation(&self) -> Representation { let mut iter = [ self.0.representation(), self.1.representation(), self.2.representation(), self.3.representation(), ] .into_iter(); Representation::from_sequence(&mut iter) } } impl Sequence for (P1, P2, P3, P4, P5) where I: ParserInput, P1: Parser, P2: Parser, P3: Parser, P4: Parser, P5: Parser, { fn parse(&self, input: I) -> ParseResult { let parser1 = &self.0; let parser2 = &self.1; let parser3 = &self.2; let parser4 = &self.3; let parser5 = &self.4; let (result1, rest1) = parser1.parse(input)?; let (result2, rest2) = parser2.parse(rest1)?; let (result3, rest3) = parser3.parse(rest2)?; let (result4, rest4) = parser4.parse(rest3)?; let (result5, rest5) = parser5.parse(rest4)?; Ok(((result1, result2, result3, result4, result5), rest5)) } fn representation(&self) -> Representation { let mut iter = [ self.0.representation(), self.1.representation(), self.2.representation(), self.3.representation(), self.4.representation(), ] .into_iter(); Representation::from_sequence(&mut iter) } } #[cfg(test)] mod test { use super::*; use crate::combinators::repeated; use crate::primitives::{identifier, literal}; #[test] fn test_tuple2() { let p = tuple2(identifier, tuple2(literal(" "), literal("ruts"))); let (output, _rest) = p.parse("fort1 ruts").unwrap(); assert_eq!(output, ("fort1".into(), (" ", "ruts"))); let p = identifier.then(literal(" ")).then(literal("ruts")); let (output, _rest) = p.parse("fort1 ruts").unwrap(); assert_eq!(output, (("fort1".into(), " "), "ruts")); } #[test] fn test_seq() { let p = seq(( literal("bong").to(10), repeated(literal(" ")).to(()), literal("hits").to(20), )); assert_eq!(p.parse("bong hits").unwrap(), ((10, (), 20), "")); let p = seq(( literal("alpha").to(10), repeated(literal(" ")).to(()), repeated(literal("-")).to(()), repeated(literal(" ")), literal("beta"), )); assert_eq!( p.parse("alpha ------ beta gamma").unwrap(), ((10, (), (), vec![" ", " ", " "], "beta"), " gamma") ); } }