use anyhow::{Result, Context, anyhow}; use mipl::prelude::*; pub fn tokenize(src: String) -> Parser { let del_param = DelimitersParam{ discard: DiscardDelimiters::new( vec![ ' ', '\n', '\t' ] ), keep: KeepDelimiters::new( vec![ '(', ')', '~', '&', '|', '=', '>', '<', '*', '#' ] ) }; Parser::from(src, del_param) } #[derive(Debug)] pub struct Parsers { /// L-expr parser pub l_parser: Parser, /// State-expr parser pub s_parser: Parser, /// The number of steps to take pub steps: usize } impl Parsers { pub fn new(parser: &mut Parser) -> Result { let states: Vec = vec!["*", "#"] .into_iter() .map(String::from) .collect(); let mut l_parser = CollectUntil::::subparse(states.clone(), parser); if l_parser.peek().is_none() { return Err(anyhow!( "No L-expr found. Refer to https://ecaxpr-book.pages.dev/langref if confused." )) } if parser.peek().is_none() { return Err(anyhow!( "No State-expr found. Refer to https://ecaxpr-book.pages.dev/langref if confused" )) }; let s_parser = CollectWhile::::subparse(states, parser); let steps: usize = match parser.next() { Some(Token::Str(s)) => s.parse().with_context(|| format!( "Failed to parse Steps-expr. Refer to https://ecaxpr-book.pages.dev/langref if confused" ) ), _ => Err(anyhow!( "Number of steps to take not given." )) }?; Ok(Parsers { l_parser, s_parser, steps }) } }