simple_ll/
lib.rs

1#![forbid(missing_docs, missing_debug_implementations)]
2
3//! A simple parser library for Rust.
4
5type Stack<'a, T> = &'a mut Vec<T>;
6type Parser<N, T> = fn(Stack<T>) -> Option<N>;
7
8/// Parser for consuming and testing a single token.
9/// Takes a function and the stack as input.
10/// The input function should convert the token into the parse node.
11pub fn enum_parse<N, T>(f: fn(&T) -> Option<N>, stack: Stack<T>) -> Option<N> {
12    match stack.pop() {
13        Some(t) => match f(&t) {
14            Some(n) => Some(n),
15            None => {
16                stack.push(t);
17                None
18            }
19        },
20        None => None,
21    }
22}
23
24// Please don't clone
25/// Trys different parsers from a list until one works.
26/// The first argument is the list of parsers, and the second is the stack.
27pub fn options_parse<N, T: Clone>(l: &[Parser<N, T>], stack: Stack<T>) -> Option<N> {
28    for p in l.iter() {
29        if let Some(n) = p(stack) {
30            return Some(n);
31        }
32    }
33    None
34}
35
36/// Uses a parser as many times as possible, then returns a vec of nodes
37pub fn repeated_parse<N, T>(p: Parser<N, T>, stack: Stack<T>) -> Vec<N> {
38    let mut res: Vec<N> = Vec::new();
39    loop {
40        match p(stack) {
41            Some(s) => res.push(s),
42            None => return res,
43        };
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use crate::{enum_parse, options_parse, repeated_parse, Stack};
50
51    #[derive(Debug, PartialEq)]
52    enum Enum1 {
53        Even,
54        Odd,
55        Zero,
56    }
57
58    fn enum_parse_1(stack: Stack<i32>) -> Option<Enum1> {
59        enum_parse(
60            |&n| {
61                if n < 0 {
62                    None
63                } else if n == 0 {
64                    Some(Enum1::Zero)
65                } else if n % 2 == 0 {
66                    Some(Enum1::Even)
67                } else {
68                    Some(Enum1::Odd)
69                }
70            },
71            stack,
72        )
73    }
74
75    #[test]
76    fn enum_parse_1_ok() {
77        assert_eq!(enum_parse_1(&mut vec![-32, 25, 0]), Some(Enum1::Zero));
78        assert_eq!(enum_parse_1(&mut vec![-32, 25, 23]), Some(Enum1::Odd));
79        assert_eq!(enum_parse_1(&mut vec![-32, 25, 2]), Some(Enum1::Even));
80    }
81
82    #[test]
83    fn enum_parse_1_err() {
84        assert_eq!(enum_parse_1(&mut vec![-32, 25, -2]), None);
85        assert_eq!(enum_parse_1(&mut vec![]), None);
86    }
87
88    #[derive(Debug, PartialEq)]
89    enum Enum2 {
90        Small,
91        Tiny,
92    }
93
94    fn enum_parse_2(stack: Stack<i32>) -> Option<Enum2> {
95        enum_parse(
96            |&n| {
97                if n > -10 && n < 0 {
98                    Some(Enum2::Small)
99                } else if n <= -10 {
100                    Some(Enum2::Tiny)
101                } else {
102                    None
103                }
104            },
105            stack,
106        )
107    }
108
109    #[test]
110    fn enum_parse_2_ok() {
111        assert_eq!(enum_parse_2(&mut vec![-32, 25, -5]), Some(Enum2::Small));
112        assert_eq!(enum_parse_2(&mut vec![-32, 25, -20]), Some(Enum2::Tiny));
113    }
114
115    #[test]
116    fn enum_parse_2_err() {
117        assert_eq!(enum_parse_2(&mut vec![-32, 25, 2]), None);
118        assert_eq!(enum_parse_2(&mut vec![]), None);
119    }
120
121    #[derive(Debug, PartialEq)]
122    enum Enum1And2 {
123        Is1(Enum1),
124        Is2(Enum2),
125    }
126
127    fn options_parse_1(stack: Stack<i32>) -> Option<Enum1And2> {
128        options_parse(
129            &[
130                |s| enum_parse_1(s).map(Enum1And2::Is1),
131                |s| enum_parse_2(s).map(Enum1And2::Is2),
132            ],
133            stack,
134        )
135    }
136
137    #[test]
138    fn options_parse_1_ok() {
139        assert_eq!(
140            options_parse_1(&mut vec![5]),
141            Some(Enum1And2::Is1(Enum1::Odd))
142        );
143        assert_eq!(
144            options_parse_1(&mut vec![0]),
145            Some(Enum1And2::Is1(Enum1::Zero))
146        );
147        assert_eq!(
148            options_parse_1(&mut vec![-1]),
149            Some(Enum1And2::Is2(Enum2::Small))
150        );
151        assert_eq!(
152            options_parse_1(&mut vec![-20]),
153            Some(Enum1And2::Is2(Enum2::Tiny))
154        );
155    }
156
157    fn repeated_parse_1(stack: Stack<i32>) -> Vec<Enum1> {
158        repeated_parse(enum_parse_1, stack)
159    }
160
161    #[test]
162    fn repeated_parse_1_ok() {
163        assert_eq!(
164            repeated_parse_1(&mut vec![-1, 3, 2, 1]),
165            vec![Enum1::Odd, Enum1::Even, Enum1::Odd]
166        );
167        assert_eq!(repeated_parse_1(&mut vec![]), vec![]);
168        assert_eq!(repeated_parse_1(&mut vec![-1]), vec![]);
169    }
170
171    fn repeated_parse_2(stack: Stack<i32>) -> Vec<Enum1And2> {
172        repeated_parse(options_parse_1, stack)
173    }
174
175    #[test]
176    fn repeated_parse_2_ok() {
177        assert_eq!(
178            repeated_parse_2(&mut vec![-1, 3, 2, 1]),
179            vec![
180                Enum1And2::Is1(Enum1::Odd),
181                Enum1And2::Is1(Enum1::Even),
182                Enum1And2::Is1(Enum1::Odd),
183                Enum1And2::Is2(Enum2::Small)
184            ]
185        );
186    }
187}