Tiny expressions-based language for elementary cellular automata simulation
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}