Mercurial > lbo > hg > rcombinators
changeset 3:ff95584ff3c9
Implement Sequence combinator
author | Lewin Bormann <lewin@lewin-bormann.info> |
---|---|
date | Thu, 30 May 2019 11:18:31 +0200 |
parents | 24646d806b4d |
children | 88dc74ffd497 |
files | src/combinators.rs src/primitives.rs src/state.rs |
diffstat | 3 files changed, 98 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- a/src/combinators.rs Thu May 30 00:40:34 2019 +0200 +++ b/src/combinators.rs Thu May 30 11:18:31 2019 +0200 @@ -1,41 +1,110 @@ -use crate::parser::{ParseError, ParseResult, Parser}; +use crate::parser::{ParseResult, Parser}; use crate::state::ParseState; pub struct Sequence<T> { t: T, } -impl<P1: Parser, P2: Parser> Parser for Sequence<(P1, P2)> { - type Result = (P1::Result, P2::Result); - fn parse( - &mut self, - st: &mut ParseState<impl Iterator<Item = char>>, - ) -> ParseResult<Self::Result> { - let hold = st.hold(); - let r1 = self.t.0.parse(st); - if r1.is_err() { - st.reset(hold); - return Err(r1.err().unwrap()); +impl<T> Sequence<T> { + pub fn new(tuple: T) -> Sequence<T> { + Sequence { t: tuple } + } +} + +macro_rules! seq_impl { + ( ( $($ptype:ident/$ix:tt),+ ) ) => { + impl<$($ptype : Parser<Result=impl Default>, )*> Parser for Sequence<($($ptype,)*)> { + type Result = ($($ptype::Result,)*); + fn parse(&mut self, st: &mut ParseState<impl Iterator<Item = char>>) -> ParseResult<Self::Result> { + let hold = st.hold(); + let mut result = Self::Result::default(); + $( + let r = (self.t.$ix).parse(st); + if r.is_err() { + st.reset(hold); + return Err(r.err().unwrap()); + } + result.$ix = r.unwrap(); + )* + st.release(hold); + return Ok(result); + } } - let r2 = self.t.1.parse(st); - if r2.is_err() { - st.reset(hold); - return Err(r2.err().unwrap()); - } - st.release(hold); - return Ok((r1.unwrap(), r2.unwrap())); } } +seq_impl!((P0 / 0, P1 / 1)); +seq_impl!((P0 / 0, P1 / 1, P2 / 2)); +seq_impl!((P0 / 0, P1 / 1, P2 / 2, P3 / 3)); +seq_impl!((P0 / 0, P1 / 1, P2 / 2, P3 / 3, P4 / 4)); +seq_impl!((P0 / 0, P1 / 1, P2 / 2, P3 / 3, P4 / 4, P5 / 5)); +seq_impl!((P0 / 0, P1 / 1, P2 / 2, P3 / 3, P4 / 4, P5 / 5, P6 / 6)); +seq_impl!(( + P0 / 0, + P1 / 1, + P2 / 2, + P3 / 3, + P4 / 4, + P5 / 5, + P6 / 6, + P7 / 7 +)); +seq_impl!(( + P0 / 0, + P1 / 1, + P2 / 2, + P3 / 3, + P4 / 4, + P5 / 5, + P6 / 6, + P7 / 7, + P8 / 8 +)); +seq_impl!(( + P0 / 0, + P1 / 1, + P2 / 2, + P3 / 3, + P4 / 4, + P5 / 5, + P6 / 6, + P7 / 7, + P8 / 8, + P9 / 9 +)); + #[cfg(test)] mod tests { use super::*; + use crate::parser::Parser; use crate::primitives::*; #[test] fn test_pair() { - let mut p = (Int, StringParser(" aaa".to_string())); + let mut p = Sequence::new((Int, StringParser::new(" aba".to_string()))); let mut ps = ParseState::new("123 aba"); - assert_eq!(Ok((123, " aaa".to_string())), p.parse(&mut ps)); + assert_eq!(Ok((123, " aba".to_string())), p.parse(&mut ps)); + } + + #[test] + fn test_long_seq() { + let s = (|| StringParser::new("a")); + let mut p = Sequence::new((s(), s(), s(), s(), s(), s(), s(), s(), s(), s())); + let mut ps = ParseState::new("aaaaaaaaaa"); + assert_eq!( + Ok(( + "a".to_string(), + "a".to_string(), + "a".to_string(), + "a".to_string(), + "a".to_string(), + "a".to_string(), + "a".to_string(), + "a".to_string(), + "a".to_string(), + "a".to_string() + )), + p.parse(&mut ps) + ); } }
--- a/src/primitives.rs Thu May 30 00:40:34 2019 +0200 +++ b/src/primitives.rs Thu May 30 11:18:31 2019 +0200 @@ -1,7 +1,11 @@ use crate::parser::{ParseError, ParseResult, Parser}; use crate::state::ParseState; -pub struct StringParser(pub String); +pub struct StringParser(String); + +impl StringParser { + pub fn new<S: AsRef<str>>(s: S) -> StringParser { StringParser(s.as_ref().to_owned()) } +} impl Parser for StringParser { type Result = String; @@ -76,7 +80,7 @@ #[test] fn test_parse_string() { let mut s = ParseState::new("abc def"); - let mut p = StringParser("abc ".to_owned()); + let mut p = StringParser::new("abc ".to_owned()); assert_eq!(Ok("abc ".to_owned()), p.parse(&mut s)); assert_eq!(4, s.index()); } @@ -85,7 +89,7 @@ fn test_parse_int() { let mut s = ParseState::new("-1252 353"); let mut ip = Int; - let mut sp = StringParser(" ".to_string()); + let mut sp = StringParser::new(" ".to_string()); assert_eq!(Ok(-1252), ip.parse(&mut s)); assert_eq!(Ok(" ".to_string()), sp.parse(&mut s)); assert_eq!(Ok(353), ip.parse(&mut s));
--- a/src/state.rs Thu May 30 00:40:34 2019 +0200 +++ b/src/state.rs Thu May 30 11:18:31 2019 +0200 @@ -151,7 +151,7 @@ assert_eq!(Some('H'), ps.next()); assert_eq!( Ok("üð".to_string()), - primitives::StringParser("üð".to_string()).parse(&mut ps) + primitives::StringParser::new("üð".to_string()).parse(&mut ps) ); } }