Minimal Imperative Parsing Library | https://docs.rs/mipl

rename and fix end token advancing bug in collect_until

ecsolticia.bsky.social 52b73e42 833e89b5

verified
Changed files
+78 -9
src
parser
tests
+2 -2
src/parser/subparser.rs
··· 26 C: concrete_parser::ContainerCp; 27 } 28 29 - mod collect_till; 30 mod collect_while; 31 mod collect_if_sequence; 32 pub use { 33 - collect_till::CollectTill, 34 collect_while::CollectWhile, 35 collect_if_sequence::{CollectIfSeq, CollectIfExactSeq}, 36 };
··· 26 C: concrete_parser::ContainerCp; 27 } 28 29 + mod collect_untill; 30 mod collect_while; 31 mod collect_if_sequence; 32 pub use { 33 + collect_untill::CollectUntill, 34 collect_while::CollectWhile, 35 collect_if_sequence::{CollectIfSeq, CollectIfExactSeq}, 36 };
+3 -3
src/parser/subparser/collect_till.rs src/parser/subparser/collect_untill.rs
··· 5 /// 6 /// Said concrete pattern here is provided by 7 /// the generic parameter `Op`. 8 - pub struct CollectTill<Op: ConcreteParser>(Op); 9 - impl<Op> ConcreteSubparser<Op> for CollectTill<Op> 10 where 11 Op: ConcreteParser 12 { ··· 20 let mut tokens: Tokens = Tokens::new_empty(); 21 22 loop { 23 - if let Some(_token) = op.try_next_token(parser) { 24 break; 25 } else { 26 if let Some(token) = parser.next() {
··· 5 /// 6 /// Said concrete pattern here is provided by 7 /// the generic parameter `Op`. 8 + pub struct CollectUntill<Op: ConcreteParser>(Op); 9 + impl<Op> ConcreteSubparser<Op> for CollectUntill<Op> 10 where 11 Op: ConcreteParser 12 { ··· 20 let mut tokens: Tokens = Tokens::new_empty(); 21 22 loop { 23 + if let Some(_token) = op.peek_for_token(parser) { 24 break; 25 } else { 26 if let Some(token) = parser.next() {
+73 -4
tests/test_subparser.rs
··· 35 } 36 37 #[test] 38 - fn test_collect_till_exact_match_subparser() { 39 let mut parser = setup_space_seps_parser( 40 "a b c d e f g h" 41 ); ··· 43 "a b c d" 44 ); 45 46 - let mut subparser = CollectTill::<ExactMatch>::subparse( 47 "e".to_string(), 48 &mut parser 49 ); ··· 56 } 57 58 #[test] 59 - fn test_collect_till_is_newline() { 60 let mut parser = setup_space_seps_parser( 61 "a b\n c d e f g h" 62 ); ··· 64 "a b" 65 ); 66 67 - let mut subparser = CollectTill::<IsNewline>::subparse( 68 (), 69 &mut parser 70 ); ··· 195 println!("{:#?}", parser); 196 197 assert_parsers_same_till(parser, initial_parser, 4); 198 }
··· 35 } 36 37 #[test] 38 + fn test_collect_untill_exact_match_subparser() { 39 let mut parser = setup_space_seps_parser( 40 "a b c d e f g h" 41 ); ··· 43 "a b c d" 44 ); 45 46 + let mut subparser = CollectUntill::<ExactMatch>::subparse( 47 "e".to_string(), 48 &mut parser 49 ); ··· 56 } 57 58 #[test] 59 + fn test_collect_untill_is_newline() { 60 let mut parser = setup_space_seps_parser( 61 "a b\n c d e f g h" 62 ); ··· 64 "a b" 65 ); 66 67 + let mut subparser = CollectUntill::<IsNewline>::subparse( 68 (), 69 &mut parser 70 ); ··· 195 println!("{:#?}", parser); 196 197 assert_parsers_same_till(parser, initial_parser, 4); 198 + } 199 + 200 + 201 + pub fn tokenize(src: String) -> Parser { 202 + let del_param = DelimitersParam{ 203 + discard: DiscardDelimiters::new( 204 + vec![ 205 + ' ', 206 + '\n', 207 + '\t' 208 + ] 209 + ), 210 + keep: KeepDelimiters::new( 211 + vec![ 212 + '(', 213 + ')', 214 + '~', 215 + '&', 216 + '|', 217 + '=', 218 + '>', 219 + '<', 220 + '*', 221 + '#' 222 + ] 223 + ) 224 + }; 225 + 226 + Parser::from(src, del_param) 227 + } 228 + 229 + #[derive(Debug)] 230 + pub struct Parsers { 231 + /// The parser for expressions 232 + expr_parser: Parser, 233 + /// The parser for initial configuration 234 + states_parser: Parser, 235 + /// The number of steps to take 236 + steps: usize 237 + } 238 + impl Parsers { 239 + pub fn new(parser: &mut Parser) -> Option<Self> { 240 + let states = vec!["*", "#"]; 241 + let expr_parser = CollectUntill::<OrExactMatch>::subparse(states.clone(), parser); 242 + let states_parser = CollectWhile::<OrExactMatch>::subparse(states, parser); 243 + let steps: usize = match parser.next() { 244 + Some(Token::Str(s)) => s.parse().ok(), 245 + _ => None 246 + }?; 247 + 248 + Some(Parsers { 249 + expr_parser, 250 + states_parser, 251 + steps 252 + }) 253 + } 254 + } 255 + 256 + #[test] 257 + fn test_until_doesnt_eat_ending() { 258 + let src = "(l | r) & (~l | ~r) **# 16".to_string(); 259 + 260 + let mut flat_parser = tokenize(src); 261 + 262 + let known_parser_a = tokenize("**#".to_string()); 263 + 264 + let parsers = Parsers::new(&mut flat_parser).unwrap(); 265 + 266 + assert_parsers_same_till(known_parser_a, parsers.states_parser, 3); 267 }