Tiny expressions-based language for elementary cellular automata simulation
at main 80 lines 2.1 kB view raw
1use anyhow::{Result, Context, anyhow}; 2use mipl::prelude::*; 3 4pub fn tokenize(src: String) -> Parser { 5 let del_param = DelimitersParam{ 6 discard: DiscardDelimiters::new( 7 vec![ 8 ' ', 9 '\n', 10 '\t' 11 ] 12 ), 13 keep: KeepDelimiters::new( 14 vec![ 15 '(', 16 ')', 17 '~', 18 '&', 19 '|', 20 '=', 21 '>', 22 '<', 23 '*', 24 '#' 25 ] 26 ) 27 }; 28 29 Parser::from(src, del_param) 30} 31 32#[derive(Debug)] 33pub struct Parsers { 34 /// L-expr parser 35 pub l_parser: Parser, 36 /// State-expr parser 37 pub s_parser: Parser, 38 /// The number of steps to take 39 pub steps: usize 40} 41impl Parsers { 42 pub fn new(parser: &mut Parser) -> Result<Self> { 43 let states: Vec<String> = vec!["*", "#"] 44 .into_iter() 45 .map(String::from) 46 .collect(); 47 48 let mut l_parser = CollectUntil::<OrExactMatch>::subparse(states.clone(), parser); 49 50 if l_parser.peek().is_none() { 51 return Err(anyhow!( 52 "No L-expr found. Refer to https://ecaxpr-book.pages.dev/langref if confused." 53 )) 54 } 55 56 if parser.peek().is_none() { 57 return Err(anyhow!( 58 "No State-expr found. Refer to https://ecaxpr-book.pages.dev/langref if confused" 59 )) 60 }; 61 let s_parser = CollectWhile::<OrExactMatch>::subparse(states, parser); 62 63 let steps: usize = match parser.next() { 64 Some(Token::Str(s)) => s.parse().with_context(|| 65 format!( 66 "Failed to parse Steps-expr. Refer to https://ecaxpr-book.pages.dev/langref if confused" 67 ) 68 ), 69 _ => Err(anyhow!( 70 "Number of steps to take not given." 71 )) 72 }?; 73 74 Ok(Parsers { 75 l_parser, 76 s_parser, 77 steps 78 }) 79 } 80}